Michael
Michael

Reputation: 41

flatten a list in linq using c#

I used linq to create a list of IO_EQUATIONS. An IO_EQUATION consists of a single OUTPUT_POINT and a List of INPUT_POINT. INPUT_POINT and OUTPUT_POINT have a common x, y, and z coordinate but they contain other fields that are not common. I want to flatten out the List of IO_EQUATIONS to either an anonymous type or a specific point type (x, y, and z only) so that I see the Output followed by all the inputs for each IO_EQUATION in a list.

I was able to use linq to list all the OUTPUT_POINTS using the following code. list41 is the list of IO_EQUATIONS

var flat = (from d2 in list41
            select (new BINARY_IO()
              {
                 propX = d2.propOutputPoint.propX,
                 propY = d2.propOutputPoint.propY,
                 propZ = d2.propOutputPoint.propZ,
                 propDir = POINT_DIRECTION_Types.Output,
              })).ToList();

I was able to use linq to list all the INPUT_POINTS using the following code. list41 is the list of IO_EQUATIONS. propIOPointList is my list of INPUT_POINT

var flat = (from d2 in list41
            from d3 in d2.propIOPointList
            select (new BINARY_IO()
                 {
                    propX = d3.propX,
                    propY = d3.propY,
                    propZ = d3.propZ,
                    propDir = POINT_DIRECTION_Types.Input,
                 })).ToList();

I can get the information separately by I want the data to be formatted as an output followed by the inputs, then the next output followed by the inputs, etc.

I have a feeling this is really simple and I just can't get it to work.

Thanks

Upvotes: 0

Views: 368

Answers (2)

Guvante
Guvante

Reputation: 19203

The easiest way is to transform each item in list41 into an IEnumerable<BINARY_IO> in the order you listed, then using SelectMany to flatten the resulting IEnumerable<IEnumerable<BINARY_IO>>.

var flat =
    (from d2 in list41
     select
        Enumerable.Repeat(
            new BINARY_IO {
                propX = d2.propOutputPoint.propX,
                propY = d2.propOutputPoint.propY,
                propZ = d2.propOutputPoint.propZ,
                propDir = POINT_DIRECTION_Types.Output}, 1)
            .Concat(
                from d3 in d2.propIOPointList
                select new BINARY_IO {
                    propX = d3.propX,
                    propY = d3.propY,
                    propZ = d3.propZ,
                    propDir = POINT_DIRECTION_Types.Input}))
    .SelectMany(i => i)
    .ToList();

Note that I use Enumerable.Repeat(v, 1) to get a singleton, there are other methods as well.

Additionally you could inline the call to SelectMany but at that point you might want to switch away from query syntax and just use a manual call to Select for the second from/select.

Upvotes: 1

Bruno
Bruno

Reputation: 4655

To flatten a list of list in LINQ, use .SelectMany

var flattenedList = list1.SelectMany(i => i.PropertyThatIsAList)

Many similar questions, for example : Flatten List in LINQ

Upvotes: 1

Related Questions