## Group by in LINQ

### Question

Let's suppose if we have a class like:

``````class Person {
internal int PersonID;
internal string car;
}
``````

I have a list of this class: `List<Person> persons;`

And this list can have multiple instances with same `PersonID`s, for example:

``````persons[0] = new Person { PersonID = 1, car = "Ferrari" };
persons[1] = new Person { PersonID = 1, car = "BMW"     };
persons[2] = new Person { PersonID = 2, car = "Audi"    };
``````

Is there a way I can group by `PersonID` and get the list of all the cars he has?

For example, the expected result would be

``````class Result {
int PersonID;
List<string> cars;
}
``````

So after grouping, I would get:

``````results[0].PersonID = 1;
List<string> cars = results[0].cars;

result[1].PersonID = 2;
List<string> cars = result[1].cars;
``````

From what I have done so far:

``````var results = from p in persons
group p by p.PersonID into g
select new { PersonID = g.Key, // this is where I am not sure what to do
``````

Could someone please point me in the right direction?

2020/06/11
1
1078
6/11/2020 8:49:54 AM

Absolutely - you basically want:

``````var results = from p in persons
group p.car by p.PersonId into g
select new { PersonId = g.Key, Cars = g.ToList() };
``````

Or as a non-query expression:

``````var results = persons.GroupBy(
p => p.PersonId,
p => p.car,
(key, g) => new { PersonId = key, Cars = g.ToList() });
``````

Basically the contents of the group (when viewed as an `IEnumerable<T>`) is a sequence of whatever values were in the projection (`p.car` in this case) present for the given key.

For more on how `GroupBy` works, see my Edulinq post on the topic.

(I've renamed `PersonID` to `PersonId` in the above, to follow .NET naming conventions.)

Alternatively, you could use a `Lookup`:

``````var carsByPersonId = persons.ToLookup(p => p.PersonId, p => p.car);
``````

You can then get the cars for each person very easily:

``````// This will be an empty sequence for any personId not in the lookup
var carsForPerson = carsByPersonId[personId];
``````
2020/04/06
1763
4/6/2020 3:26:11 PM

``````var results = from p in persons
group p by p.PersonID into g
select new { PersonID = g.Key,
/**/car = g.Select(g=>g.car).FirstOrDefault()/**/}
``````
2014/07/24

``````var results = from p in persons
group p by p.PersonID into g
select new { PersonID = g.Key, Cars = g.Select(m => m.car) };
``````
2016/08/19

You can also Try this:

``````var results= persons.GroupBy(n => new { n.PersonId, n.car})
.Select(g => new {
g.Key.PersonId,
g.Key.car)}).ToList();
``````
2020/04/08

try

``````persons.GroupBy(x => x.PersonId).Select(x => x)
``````

or

to check if any person is repeating in your list try

``````persons.GroupBy(x => x.PersonId).Where(x => x.Count() > 1).Any(x => x)
``````
2018/06/25

I have created a working code sample with Query Syntax and Method Syntax. I hope it helps the others :)

You can also run the code on .Net Fiddle here:

``````using System;
using System.Linq;
using System.Collections.Generic;

class Person
{
public int PersonId;
public string car  ;
}

class Result
{
public int PersonId;
public List<string> Cars;
}

public class Program
{
public static void Main()
{
List<Person> persons = new List<Person>()
{
new Person { PersonId = 1, car = "Ferrari" },
new Person { PersonId = 1, car = "BMW" },
new Person { PersonId = 2, car = "Audi"}
};

//With Query Syntax

List<Result> results1 = (
from p in persons
group p by p.PersonId into g
select new Result()
{
PersonId = g.Key,
Cars = g.Select(c => c.car).ToList()
}
).ToList();

foreach (Result item in results1)
{
Console.WriteLine(item.PersonId);
foreach(string car in item.Cars)
{
Console.WriteLine(car);
}
}

Console.WriteLine("-----------");

//Method Syntax

List<Result> results2 = persons
.GroupBy(p => p.PersonId,
(k, c) => new Result()
{
PersonId = k,
Cars = c.Select(cs => cs.car).ToList()
}
).ToList();

foreach (Result item in results2)
{
Console.WriteLine(item.PersonId);
foreach(string car in item.Cars)
{
Console.WriteLine(car);
}
}
}
}
``````

Here is the result:

```1
Ferrari
BMW
2
Audi
-----------
1
Ferrari
BMW
2
Audi

```
2017/11/30