2

We need to transpose data from the rows in a table to the output table such that that multiple rows are returned for every row in the input table. The logic for extracting data in each row of the output depends if value is present in a given column in the input row.

For e.g.

Input table

A, B, C, D, E, F

Output table

A, B, C, [if value present in D then some operation on value in D]

A, B, C, [if value present in E then some operation on value in E]

A, B, C, [if value present in F then some operation on value in F]

For doing this I intend to something like this:

private IEnumerable<OutputRow> BuildOutputTable(DataTable inputTable)
{
    var outputRows = from inputRow in inputTable.AsEnumerable()
                     select new outputRow(inputRow, *delegateToProcessor*);
    return gbbOutputRows;
}

But this will need me to iterate through for each of the additional value columns. Can I avoid that and just pass a single delegate so that the 'select new outputrow' returns me multiple rows?

2
  • Your input table - is that comma separated list representing 1 row with 6 columns or 6 rows with 1 column? And likewise, is your output table 3 rows with 4 columns? Its not very clear. Commented Nov 8, 2012 at 12:55
  • @Jamiec : the input table is of 6 columns and the output table is of 4 columns. Just wanted to show that each input row results in 3 output rows with the same values except in the calculated column. Commented Nov 8, 2012 at 13:21

4 Answers 4

2

Create a function like this:

public IEnumerable<OutputRow> GetOutputRows(InputRow input)
{
    if ( ** some condition on input.D ** )
        yield return new OutputRow(inputRow, *delegateToProcessor*);
    if ( ** some condition on input.E ** )
        yield return new OutputRow(inputRow, *delegateToProcessor*);
    if ( ** some condition on input.F ** )
        yield return new OutputRow(inputRow, *delegateToProcessor*);
}

and your query goes like this:

var outputRows = from inputRow in inputTable.AsEnumerable()
                 from row2 in GetOutputRows(inputRow)
                 select row2;
Sign up to request clarification or add additional context in comments.

Comments

1

I would do:

var DRows = from inputRow in inputTable.AsEnumerable()
                 where inputRow.D == 'some value'
                 select new outputRow(inputRow, *delegateToProcessor*)

var ERows = from inputRow in inputTable.AsEnumerable()
                 where inputRow.E == 'some value'
                 select new outputRow(inputRow, *delegateToProcessor*)

var FRows = from inputRow in inputTable.AsEnumerable()
                 where inputRow.F == 'some value'
                 select new outputRow(inputRow, *delegateToProcessor*)

return DRows.Union(ERows).Union(FRows);

1 Comment

I think Concat is better than Union here.
0

The select statement of linq can only select 1 object at the time. You could however select a group and afterwards do a union.
The result would look something like this :

        public static void test()
        {
            var data = new List<String>{"a","b","c","d"};
            var outputRows = from inputRow in data
                             select Expand(inputRow);
            var result = new List<String>();
            outputRows.ToList().ForEach(r=>result = r.Union(result).ToList());
        }

        private static List<String> Expand(string data)
        {
            var subdata = new List<String>();
            subdata.Add(data + "1");
            subdata.Add(data + "2");
            return subdata;
        }

Comments

0

what about this:

private IEnumerable<OutputRow> BuildOutputTable(DataTable inputTable)
{
    var tmp = from inputRow in inputTable.AsEnumerable()
              select new { x = getProcessedRows(inputRow)};
    var outputRows = tmp.SelectMany(x=>x.x);
    return outputRows;
}

private IEnumerable<OutputRow> getProcessedRows(YourInputRowType inputRow)
{
    List<OutputRow> ret = new List<OutputRow>()
    /* some logic here to generate the output rows for this input row */
    return ret;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.