Gruppieren nach in LINQ

Nehmen wir an, wir hätten eine class wie

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

Jetzt habe ich eine Liste dieser class: List persons;

Jetzt kann diese Liste mehrere Instanzen mit denselben PersonIDs haben, zum Beispiel:

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

Gibt es eine Möglichkeit, nach personID und die Liste aller Autos zu bekommen, die er hat?

Zum Beispiel wäre das erwartete Ergebnis

 class Result { int PersonID; List cars; } 

Also nach der Gruppierung würde ich bekommen:

 results[0].PersonID = 1; List cars = results[0].cars; result[1].PersonID = 2; List cars = result[1].cars; 

Von dem was ich bisher gemacht habe:

 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 

Könnte mir bitte jemand in die richtige Richtung zeigen?

   

Absolut – Sie wollen grundsätzlich:

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

Oder als Nicht-Abfrage-Ausdruck:

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

Im Grunde genommen ist der Inhalt der Gruppe (bei Betrachtung als IEnumerable ) eine Folge von beliebigen Werten, die in der Projektion ( p.car in diesem Fall) für den gegebenen Schlüssel vorhanden waren.

Weitere GroupBy zur functionsweise von GroupBy finden Sie in meinem Edulinq-Beitrag zum Thema .

(Ich habe PersonID in PersonId umbenannt, um den .NET-Namenskonventionen zu folgen.)

Alternativ könnten Sie eine Lookup :

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

Sie können dann die Autos für jede Person sehr leicht bekommen:

 // This will be an empty sequence for any personId not in the lookup var carsForPerson = carsByPersonId[personId]; 
 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()/**/} 
 var results = from p in persons group p by p.PersonID into g select new { PersonID = g.Key, Cars = g.Select(m => m.car) }; 

Sie können dies auch versuchen.

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

Versuchen

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

oder

Überprüfen Sie, ob sich eine Person in Ihrer Liste wiederholt

 persons.GroupBy(x => x.PersonId).Where(x => x.Count() > 1).Any(x => x) 

Ich habe ein funktionierendes Codebeispiel mit Abfragesyntax und Methodensyntax erstellt. Ich hoffe es hilft den anderen 🙂

Sie können den Code auch hier auf .Net Fiddle ausführen:

 using System; using System.Linq; using System.Collections.Generic; class Person { public int PersonId; public string car ; } class Result { public int PersonId; public List Cars; } public class Program { public static void Main() { List persons = new List() { new Person { PersonId = 1, car = "Ferrari" }, new Person { PersonId = 1, car = "BMW" }, new Person { PersonId = 2, car = "Audi"} }; //With Query Syntax List 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 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); } } } } 

Hier ist das Ergebnis:

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

Versuche dies :

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

Im Hinblick auf die performance ist die folgende Praxis jedoch besser und optimierter in der Speichernutzung (wenn unser Array viel mehr Elemente wie Millionen enthält):

 var carDic=new Dictionary>(); for(int i=0;i(){person.car}; } } //returns the list of cars for PersonId 1 var carList=carDic[1];