Bawię się z LINQ, aby się o tym dowiedzieć, ale nie mogę wymyślić, jak go używać, Distinct
gdy nie mam prostej listy (prosta lista liczb całkowitych jest dość łatwa do zrobienia, to nie jest pytanie). Co jeśli chcę użyć Distinct na liście Object na jednej lub więcej właściwości obiektu?
Przykład: Jeśli obiekt ma Person
właściwość Id
. Jak mogę pobrać całą Osobę i używać Distinct
na niej właściwości Id
obiektu?
Person1: Id=1, Name="Test1"
Person2: Id=1, Name="Test1"
Person3: Id=2, Name="Test2"
Jak mogę dostać sprawiedliwy Person1
i Person3
? Czy to jest możliwe?
Jeśli nie jest to możliwe z LINQ, jaki byłby najlepszy sposób posiadania listy Person
zależnej od niektórych jej właściwości w .NET 3.5?
GroupBy
jest prostsze. Jeśli potrzebujesz go w więcej niż jednym miejscu, jest o wiele czystsze (IMO), aby zawrzeć intencję.IQueryable<T>
tutaj wzmianki , nie rozumiem, jak to jest istotne. Zgadzam się, że nie byłoby to odpowiednie dla EF itp., Ale myślę, że w LINQ do Objects jest bardziej odpowiednie niżGroupBy
. Kontekst pytania jest zawsze ważny.Prosty! Chcesz je zgrupować i wybrać zwycięzcę z grupy.
Jeśli chcesz zdefiniować grupy dla wielu właściwości, oto jak:
źródło
Single()
iSingleOrDefault()
każdy rzut, gdy źródło ma więcej niż jeden przedmiot. W tej operacji oczekujemy, że każda grupa może mieć więcej niż jeden element. W tym przypadkuFirst()
jest preferowane,FirstOrDefault()
ponieważ każda grupa musi mieć co najmniej jednego członka ... chyba że używasz EntityFramework, który nie może stwierdzić, że każda grupa ma co najmniej jednego członka i wymagaFirstOrDefault()
.FirstOrDefault()
github.com/dotnet/efcore/issues/12088 Mam wersję 3.1 i dostaję błędy „nie mogę tłumaczyć”.Posługiwać się:
where
Pomaga filtrować wpisy (może być bardziej skomplikowane) igroupby
iselect
wykonać odrębną funkcję.źródło
Możesz także użyć składni zapytania, jeśli chcesz, aby wyglądała jak LINQ:
źródło
Myślę, że to wystarczy:
źródło
Najpierw zgrupuj rozwiązanie według pól, a następnie wybierz pierwszy domyślny element.
źródło
Możesz to zrobić ze standardem
Linq.ToLookup()
. Spowoduje to utworzenie zbioru wartości dla każdego unikalnego klucza. Wystarczy wybrać pierwszy element w kolekcjiźródło
Poniższy kod jest funkcjonalnie równoważny z odpowiedzią Jona Skeeta .
Testowany na .NET 4.5, powinien działać na każdej wcześniejszej wersji LINQ.
Nawiasem mówiąc, sprawdź najnowszą wersję DistinctBy.cs Jona Skeeta w Google Code .
źródło
Napisałem artykuł, który wyjaśnia, jak rozszerzyć funkcję Distinct, abyś mógł wykonać następujące czynności:
Oto artykuł: Rozszerzanie LINQ - Określanie właściwości w funkcji Distinct
źródło
Osobiście korzystam z następującej klasy:
Następnie metoda rozszerzenia:
Wreszcie zamierzone użycie:
Zaletą, którą znalazłem przy użyciu tego podejścia, jest ponowne użycie
LambdaEqualityComparer
klasy dla innych metod, które akceptująIEqualityComparer
. (Och, i pozostawiam teyield
rzeczy oryginalnej implementacji LINQ ...)źródło
Jeśli potrzebujesz metody Distinct na wielu właściwościach, możesz sprawdzić moją bibliotekę PowerfulExtensions . Obecnie jest na bardzo młodym etapie, ale już możesz używać metod takich jak Distinct, Union, Intersect, z wyjątkiem dowolnej liczby właściwości;
Oto jak go używasz:
źródło
Kiedy w naszym projekcie stanęliśmy przed takim zadaniem, zdefiniowaliśmy mały interfejs API do tworzenia komparatorów.
Przypadek użycia wyglądał tak:
A sam interfejs API wygląda następująco:
Więcej szczegółów znajduje się na naszej stronie: IEqualityComparer w LINQ .
źródło
Za pomocą DistinctBy () można uzyskać rekordy Distinct według właściwości obiektu. Po prostu dodaj następującą instrukcję przed użyciem:
a następnie użyj go w następujący sposób:
gdzie „Indeks” jest właściwością, dla której chcę, aby dane były odrębne.
źródło
Możesz to zrobić (choć nie błyskawicznie) tak:
To znaczy: „wybierz wszystkie osoby, których nie ma na liście innej osoby o tym samym identyfikatorze”.
Pamiętaj, że w twoim przykładzie wybrałbyś tylko osobę 3. Nie jestem pewien, jak powiedzieć, czego chcesz, z poprzednich dwóch.
źródło
Jeśli nie chcesz dodawać biblioteki MoreLinq do swojego projektu tylko po to, aby uzyskać
DistinctBy
funkcjonalność, możesz uzyskać ten sam wynik końcowy, używając przeciążenia metody Linq,Distinct
która przyjmujeIEqualityComparer
argument.Zaczynasz od utworzenia ogólnej niestandardowej klasy porównującej równość, która używa składni lambda do wykonania niestandardowego porównania dwóch wystąpień klasy ogólnej:
Następnie w głównym kodzie używasz go w następujący sposób:
Voila! :)
Powyższe zakłada, co następuje:
Person.Id
jest typuint
people
Zbiór nie zawiera żadnych elementów zerowychJeśli kolekcja może zawierać wartości null, po prostu przepisz lambdy, aby sprawdzić, czy null, np .:
EDYTOWAĆ
To podejście jest podobne do tego w odpowiedzi Władimira Niestierowskiego, ale jest prostsze.
Jest również podobny do tego w odpowiedzi Joela, ale pozwala na złożoną logikę porównań obejmującą wiele właściwości.
Jeśli jednak Twoje obiekty mogą się różnić tylko do tego
Id
czasu, inny użytkownik udzielił poprawnej odpowiedzi, że wszystko, co musisz zrobić, to zastąpić domyślne implementacjeGetHashCode()
iEquals()
w swojejPerson
klasie, a następnie użyćDistinct()
gotowej metody Linq do filtrowania wszystkie duplikaty.źródło
Najlepszym sposobem na zrobienie tego, który będzie kompatybilny z innymi wersjami platformy .NET, jest zastąpienie Equals i GetHash, aby sobie z tym poradzić (patrz Pytanie o przepełnieniu stosu Ten kod zwraca różne wartości. Chcę jednak zwrócić silnie typowaną kolekcję w przeciwieństwie do anonimowy typ ), ale jeśli potrzebujesz czegoś, co jest ogólne w całym kodzie, rozwiązania w tym artykule są świetne.
źródło
źródło
Select()
new Person
zamiastnew Player
? Fakt, że zamawiaszID
, w żaden sposób nie informujeDistinct()
o tym, aby użyć tej właściwości do określenia wyjątkowości, więc to nie zadziała.Zastąp metody Equals (object obj) i GetHashCode () :
a następnie wystarczy zadzwonić:
źródło
Powinieneś być w stanie przesłonić Equals na osobę, aby faktycznie zrobić Equals na Person.id. Powinno to spowodować zachowanie, którego szukasz.
źródło
Spróbuj z poniższym kodem.
źródło