Załóżmy, że mamy taką klasę:
class Person {
internal int PersonID;
internal string car;
}
Teraz mam listę tej klasy: List<Person> persons;
Teraz ta lista może mieć wiele instancji z tymi samymi PersonID
, na przykład:
persons[0] = new Person { PersonID = 1, car = "Ferrari" };
persons[1] = new Person { PersonID = 1, car = "BMW" };
persons[2] = new Person { PersonID = 2, car = "Audi" };
Czy istnieje sposób, w jaki mogę pogrupować PersonID
i uzyskać listę wszystkich samochodów, które ma?
Na przykład oczekiwany wynik to
class Result {
int PersonID;
List<string> cars;
}
Po zgrupowaniu otrzymam:
results[0].PersonID = 1;
List<string> cars = results[0].cars;
result[1].PersonID = 2;
List<string> cars = result[1].cars;
Z tego, co dotychczas zrobiłem:
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
Czy ktoś mógłby wskazać mi właściwy kierunek?
Count
iSum
tutaj stackoverflow.com/questions/3414080/…Odpowiedzi:
Oczywiście - w zasadzie chcesz:
Lub jako wyrażenie bez zapytania:
Zasadniczo zawartość grupy (gdy jest postrzegana jako
IEnumerable<T>
) jest sekwencją wszystkich wartości, które były w rzucie (p.car
w tym przypadku) obecnym dla danego klucza.Aby uzyskać więcej informacji o tym
GroupBy
, jak działa, zobacz mój post Edulinq na ten temat .(Mam przemianowany
PersonID
naPersonId
powyżej, aby śledzić .NET konwencje nazewnictwa ).Alternatywnie możesz użyć
Lookup
:Następnie możesz bardzo łatwo zdobyć samochody dla każdej osoby:
źródło
.GroupBy(p => new {p.Id, p.Name}, p => p, (key, g) => new { PersonId = key.Id, PersonName = key.Name, PersonCount = g.Count()})
a dostaniesz wszystkie osoby, które występują z identyfikatorem, nazwiskiem i liczbą wystąpień dla każdej osoby.źródło
źródło
Możesz także wypróbować:
źródło
próbować
lub
aby sprawdzić, czy jakaś osoba powtarza się na liście, spróbuj
źródło
Utworzyłem działający przykładowy kod ze składnią zapytania i składnią metody. Mam nadzieję, że pomoże innym :)
Możesz również uruchomić kod na .Net Fiddle tutaj:
Oto wynik:
źródło
Spróbuj tego :
Jednak pod względem wydajności poniższa praktyka jest lepsza i bardziej zoptymalizowana pod względem wykorzystania pamięci (gdy nasza tablica zawiera znacznie więcej elementów, takich jak miliony):
źródło
g.Key.PersonId
?g.SelectMany
?? Najwyraźniej tego nie próbowałeś.SortedDictionary <PersonIdInt, SortedDictionary <CarNameString, CarInfoClass>>
. Najbliżej mogłem uzyskać za pomocą LINQIEnumerable <IGrouping <PersonIdInt, Dictionary <CarNameString, PersonIdCarNameXrefClass>>>
. Skończyłem z użyciemfor
metody pętli, która, przy okazji, była 2x szybsza. Używałbym również: a)foreach
vs.bfor
)TryGetValue
vs.ContainsKey
(oba dla zasady DRY - w kodzie i środowisku wykonawczym).Alternatywnym sposobem na to może być wybranie odrębnego
PersonId
i dołączenie do grupy za pomocąpersons
:Lub to samo z płynną składnią API:
GroupJoin tworzy listę wpisów na pierwszej liście (lista
PersonId
w naszym przypadku), każda z grupą połączonych wpisów na drugiej liście (listapersons
).źródło
W poniższym przykładzie użyto metody GroupBy, aby zwrócić obiekty, które są pogrupowane według
PersonID
.Lub
Lub
Lub możesz użyć
ToLookup
, ZasadniczoToLookup
używaEqualityComparer<TKey>
.Default do porównywania kluczy i robienia tego, co powinieneś zrobić ręcznie podczas używania grupowania według i słownika. myślę, że to ekscytująca pamięćźródło
Najpierw ustaw pole klucza. Następnie podaj pozostałe pola:
źródło