Vahid - 1 year ago 60
C# Question

# Group items in a list based on two properties using LINQ

I have a

`Column`
class as below:

``````public class Column
{
public int LocId { get; set; }
public int SecId { get; set; }
public double StartElevation { get; set; }
public double EndElevation { get; set; }
}
``````

And a list of
`Column`
objects:

``````List<Column> Columns = new List<Column>();
``````

For example:

``````Columns:
{
Column1: { LocId = 1 , SecId = 1, StartElevation = 0, EndElevation = 160 }
Column2: { LocId = 1 , SecId = 1, StartElevation = 160, EndElevation = 320 }
Column3: { LocId = 1 , SecId = 2, StartElevation = 320, EndElevation = 640 }
Column4: { LocId = 2 , SecId = 1, StartElevation = 0, EndElevation = 160 }
Column5: { LocId = 2 , SecId = 2, StartElevation = 160, EndElevation = 320 }
}
``````

I want to apply the below algorithm to the above list using Linq.

Go through the
`Columns`
list and:

• (A) Choose a list of items that have the the same
`LocId`
.

• (B) Then from that list choose another list of items that have the same
`SecId`
.

This will give me a list hopefully which I will perform other things on it.

So applying the above algorithm on the data above will be like this.

``````                                       Columns List
---------------------------------------------------------
| Column1     Column2     Column3     Column4     Column5 |
---------------------------------------------------------
|
|
(A)
|
|
--------------------------------------------
|                                          |
GroupBasedOnLocId                         GroupBasedOnLocId
|                                          |
-----------                                 -----------
| Column1 |                                 | Column4 |
| Column2 |                                 | Column5 |
| Column3 |                                 -----------
-----------                                      |
|                                           |
(B)                                         (B)
|                                           |
-------------------------                   -------------------------
|                       |                   |                       |
|                       |                   |                       |
GroupBasedOnSecId        GroupBasedOnSecId  GroupBasedOnSecId        GroupBasedOnSecId
|                       |                   |                       |
|                       |                   |                       |
Column1                 Column3             Column4                 Column5
Column2
``````

How can I accomplish this using LINQ?

Use `.GroupBy` with composite key.

Sample code:

``````List<Column> Columns = new List<Column>
{
new Column { LocId = 1 , SecId = 1, StartElevation = 0, EndElevation = 160 },
new Column { LocId = 1 , SecId = 1, StartElevation = 160, EndElevation = 320 },
new Column { LocId = 1 , SecId = 2, StartElevation = 320, EndElevation = 640 },
new Column { LocId = 2 , SecId = 1, StartElevation = 0, EndElevation = 160 },
new Column { LocId = 2 , SecId = 2, StartElevation = 160, EndElevation = 320 }
};

foreach (var group in Columns.GroupBy(c => new { c.LocId, c.SecId }))
{
Console.WriteLine("group: LocId = {0}, SecId = {1}", group.Key.LocId, group.Key.SecId);
foreach(Column column in group)
Console.WriteLine("  item: StartElevation = {0}, EndElevation = {1}", column.StartElevation, column.EndElevation);
}
``````

You can transform the group any way you want:

``````foreach (var res in Columns.GroupBy(c => new { c.LocId, c.SecId })
.Select(g => new
{
g.Key.LocId,
g.Key.SecId,
MinStartElevation = g.Min(c => c.StartElevation),
MaxEndElevation = g.Max(c => c.EndElevation)
}))
{
Console.WriteLine("LocId = {0}, SecId = {1}, MinStartElevation = {2}, MaxEndElevation = {3}",
res.LocId, res.SecId, res.MinStartElevation, res.MinStartElevation);
}
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download