Richtig, ich habe also eine Aufzählung und möchte unterschiedliche Werte daraus ziehen.
Mit System.Linq
gibt es natürlich eine Erweiterungsmethode namens Distinct
. Im einfachen Fall kann es ohne Parameter verwendet werden, wie zum Beispiel:
var distinctValues = myStringList.Distinct();
Schön und gut, aber wenn ich eine Aufzählung von Objekten habe, für die ich Gleichheit angeben muss, ist die einzige verfügbare Überladung:
var distinctValues = myCustomerList.Distinct(someEqualityComparer);
Das Gleichheitsvergleichsargument muss eine Instanz von sein IEqualityComparer<T>
. Ich kann das natürlich, aber es ist etwas ausführlich und ungeschickt.
Was ich erwartet hätte, ist eine Überlastung, die ein Lambda benötigt, sagen wir eine Func <T, T, bool>:
var distinctValues
= myCustomerList.Distinct((c1, c2) => c1.CustomerId == c2.CustomerId);
Weiß jemand, ob es eine solche Erweiterung oder eine gleichwertige Problemumgehung gibt? Oder fehlt mir etwas?
Gibt es alternativ eine Möglichkeit, einen IEqualityComparer inline anzugeben (peinlich für mich)?
Aktualisieren
Ich habe eine Antwort von Anders Hejlsberg auf einen Beitrag in einem MSDN-Forum zu diesem Thema gefunden. Er sagt:
Das Problem, auf das Sie stoßen werden, ist, dass zwei Objekte, wenn sie gleich sind, denselben GetHashCode-Rückgabewert haben müssen (andernfalls funktioniert die von Distinct intern verwendete Hash-Tabelle nicht richtig). Wir verwenden IEqualityComparer, weil es kompatible Implementierungen von Equals und GetHashCode in einer einzigen Schnittstelle verpackt.
Ich nehme an, das macht Sinn ..
quelle
.Distinct(new KeyEqualityComparer<Customer,string>(c1 => c1.CustomerId))
und erklären, warum GetHashCode () wichtig ist, um richtig zu funktionieren.Antworten:
quelle
DistinctBy
(oder sogarDistinct
, da die Signatur eindeutig sein wird).yield
Anweisung nicht, sodass Streaming technisch nicht möglich ist. Vielen Dank für Ihre Antwort. Ich werde es beim Codieren in C # verwenden. ;-)Es sieht für mich so
DistinctBy
aus, als ob Sie von MoreLINQ wollen . Sie können dann schreiben:Hier ist eine
DistinctBy
abgespeckte Version von (keine Überprüfung der Nichtigkeit und keine Option zum Angeben eines eigenen Schlüsselvergleichs):quelle
yield
kann foreach für alle VB_Complainer über die + extra lib alsreturn source.Where(element => knownKeys.Add(keySelector(element)));
Dinge einpacken . Ich denke, die meisten Leute, die wie ich hierher gekommen sind, wollen die einfachste Lösung, die möglich ist, ohne Bibliotheken zu verwenden und mit der bestmöglichen Leistung .
(Die akzeptierte Gruppe nach Methode ist für mich meiner Meinung nach ein Overkill in Bezug auf die Leistung.)
Hier ist eine einfache Erweiterungsmethode, die die IEqualityComparer- Schnittstelle verwendet und auch für Nullwerte funktioniert.
Verwendungszweck:
Code der Erweiterungsmethode
quelle
Nein, dafür gibt es keine solche Überlastung der Erweiterungsmethode. Ich fand das in der Vergangenheit selbst frustrierend und als solches schreibe ich normalerweise eine Hilfsklasse, um dieses Problem zu lösen. Das Ziel ist es, ein
Func<T,T,bool>
in umzuwandelnIEqualityComparer<T,T>
.Beispiel
Auf diese Weise können Sie Folgendes schreiben
quelle
IEqualityComparer<T>
aus einer Projektion zu erstellen : stackoverflow.com/questions/188120/…Kurzlösung
quelle
Dies wird tun, was Sie wollen, aber ich weiß nicht über die Leistung:
Zumindest ist es nicht ausführlich.
quelle
Hier ist eine einfache Erweiterungsmethode, die das tut, was ich brauche ...
Es ist eine Schande, dass sie keine bestimmte Methode wie diese in das Framework gebacken haben, aber hey ho.
quelle
x.Key
zux.First()
und den Rückgabewert zu ändernIEnumerable<T>
Etwas, das ich benutzt habe und das für mich gut funktioniert hat.
quelle
Alle Lösungen, die ich hier gesehen habe, beruhen auf der Auswahl eines bereits vergleichbaren Bereichs. Wenn man jedoch anders vergleichen muss, scheint diese Lösung hier allgemein zu funktionieren, für etwas wie:
quelle
Nehmen Sie einen anderen Weg:
Die Sequenz gibt unterschiedliche Elemente zurück, die sie mit der Eigenschaft '_myCaustomerProperty' vergleichen.
quelle
Sie können InlineComparer verwenden
Anwendungsbeispiel :
Quelle: https://stackoverflow.com/a/5969691/206730
Verwenden von IEqualityComparer für Union Kann ich meinen expliziten Typkomparator
inline angeben?
quelle
Sie können LambdaEqualityComparer verwenden:
quelle
Eine schwierige Möglichkeit hierfür ist die Verwendung der
Aggregate()
Erweiterung, bei der ein Wörterbuch als Akkumulator mit den Schlüsseleigenschaftswerten als Schlüssel verwendet wird:Und eine GroupBy-ähnliche Lösung verwendet
ToLookup()
:quelle
Dictionary<int, Customer>
?Ich gehe davon aus, dass Sie eine IEnumerable haben und in Ihrem Beispieldelegierten möchten Sie, dass c1 und c2 auf zwei Elemente in dieser Liste verweisen?
Ich glaube, Sie könnten dies mit einem Self-Join erreichen. Var differentResults = from c1 in myList join c2 in myList on
quelle
Wenn Sie
Distinct()
keine eindeutigen Ergebnisse erzielen, versuchen Sie Folgendes:quelle
Das Microsoft System.Interactive-Paket enthält eine Version von Distinct, die ein Lambda für die Schlüsselauswahl verwendet. Dies ist praktisch die gleiche Lösung wie die von Jon Skeet, kann jedoch hilfreich sein, damit die Benutzer sie kennen und den Rest der Bibliothek überprüfen können.
quelle
So geht's:
Mit dieser Methode können Sie sie verwenden, indem Sie einen Parameter wie
.MyDistinct(d => d.Name)
angeben, aber Sie können auch eine Bedingung mit einem zweiten Parameter wie folgt angeben:Hinweis: Auf diese Weise können Sie auch andere Funktionen wie z. B. angeben
.LastOrDefault(...)
.Wenn Sie nur die Bedingung verfügbar machen möchten, können Sie sie noch einfacher gestalten, indem Sie sie wie folgt implementieren:
In diesem Fall würde die Abfrage nur so aussehen:
NB Hier ist der Ausdruck einfacher, aber Note
.MyDistinct2
verwendet.FirstOrDefault(...)
implizit.Hinweis: In den obigen Beispielen wird die folgende Demo-Klasse verwendet
quelle
IEnumerable
Lambda-Erweiterung:Verwendungszweck:
quelle