Ich möchte den Inhalt einiger Sammlungen in meiner Equals-Methode vergleichen. Ich habe ein Wörterbuch und eine IList. Gibt es eine eingebaute Methode, um dies zu tun?
Bearbeitet: Ich möchte zwei Wörterbücher und zwei IListen vergleichen, daher denke ich, dass die Bedeutung von Gleichheit klar ist. Wenn die beiden Wörterbücher dieselben Schlüssel enthalten, die denselben Werten zugeordnet sind, sind sie gleich.
c#
.net
collections
TimK
quelle
quelle
IList
? Die Frage ist nicht eindeutig.Enumerable.SequenceEqual
undISet.SetEquals
stellen Versionen dieser Funktionalität bereit. Wenn Sie auftragsunabhängig sein und mit Sammlungen arbeiten möchten, die Duplikate enthalten, müssen Sie Ihre eigenen rollen. Schauen Sie sich die in diesem BeitragAntworten:
Enumerable.SequenceEqual
Sie können die Liste und das Wörterbuch nicht direkt vergleichen, aber Sie können die Liste der Werte aus dem Wörterbuch mit der Liste vergleichen
quelle
.Keys
und.Values
kann daher die Schlüssel und Werte in beliebiger Reihenfolge zurückgeben. Diese Reihenfolge wird sich wahrscheinlich ändern, wenn auch das Wörterbuch geändert wird. Ich schlage vor, Sie lesen nach, was ein Wörterbuch ist und was nicht.Wie andere vorgeschlagen und festgestellt haben,
SequenceEqual
ist es auftragsabhängig. Um dies zu lösen, können Sie das Wörterbuch nach Schlüssel sortieren (was eindeutig ist und die Sortierung daher immer stabil ist) und dann verwendenSequenceEqual
. Der folgende Ausdruck prüft, ob zwei Wörterbücher unabhängig von ihrer internen Reihenfolge gleich sind:EDIT: Wie von Jeppe Stig Nielsen hervorgehoben, haben einige Objekte eine
IComparer<T>
, die mit ihren nicht kompatibel istIEqualityComparer<T>
, was zu falschen Ergebnissen führt. Wenn Sie Schlüssel mit einem solchen Objekt verwenden, müssen Sie eine KorrekturIComparer<T>
für diese Schlüssel angeben . Bei Zeichenfolgenschlüsseln (bei denen dieses Problem auftritt) müssen Sie beispielsweise Folgendes tun, um korrekte Ergebnisse zu erhalten:quelle
CompareTo
tut? Ihre Lösung wird dann explodieren. Was ist, wenn der Schlüsseltyp einen Standardvergleicher hat, der nicht mit seinem Standardgleichheitsvergleich kompatibel ist? Dies ist der Fall fürstring
, wissen Sie. Als Beispiel werden diese Wörterbücher (mit impliziten Standard-Gleichheitsvergleichen) Ihren Test nicht bestehen (unter allen mir bekannten Kulturinformationen):var dictionary1 = new Dictionary<string, int> { { "Strasse", 10 }, { "Straße", 20 }, }; var dictionary2 = new Dictionary<string, int> { { "Straße", 20 }, { "Strasse", 10 }, };
IComparer
und betrifftIEqualityComparer
- ich war mir dieses Problems nicht bewusst, sehr interessant! Ich habe die Antwort mit einer möglichen Lösung aktualisiert. Über den Mangel anCompareTo
, ich denke , die Entwickler sollten Sie die Delegierten der bereitgestellten machenOrderBy()
Methode gibt etwas Vergleichbares. Ich denke, dies gilt für jede Verwendung oderOrderBy()
auch außerhalb von Wörterbuchvergleichen.Neben der erwähnten SequenceEqual , die
(Dies kann der Standardvergleich sein, dh eine Überschreibung
Equals()
)Es ist erwähnenswert, dass es in .Net4 SetEquals für
ISet
Objekte gibt, dieWenn Sie also eine Liste von Objekten haben möchten, diese jedoch nicht in einer bestimmten Reihenfolge vorliegen müssen, sollten Sie berücksichtigen, dass ein
ISet
(wie aHashSet
) die richtige Wahl sein kann.quelle
Schauen Sie sich die Enumerable.SequenceEqual- Methode an
quelle
.NET Es fehlen leistungsstarke Tools zum Vergleichen von Sammlungen. Ich habe eine einfache Lösung entwickelt, die Sie unter dem folgenden Link finden:
http://robertbouillon.com/2010/04/29/comparing-collections-in-net/
Dadurch wird unabhängig von der Reihenfolge ein Gleichheitsvergleich durchgeführt:
Dadurch wird überprüft, ob Elemente hinzugefügt / entfernt wurden:
Dadurch wird angezeigt, welche Elemente im Wörterbuch geändert wurden:
quelle
.Removed
ist das gleiche wielist1.Except(list2)
,.Added
istlist2.Except(list1)
,.Equal
istlist1.Intersect(list2)
und.Different
istoriginal.Join(changed, left => left.Key, right => right.Key, (left, right) => left.Value == right.Value)
. Sie können fast jeden Vergleich mit LINQ durchführen..Different
istoriginal.Join(changed, left => left.Key, right => right.Key, (left, right) => new { Key = left.Key, NewValue = right.Value, Different = left.Value == right.Value).Where(d => d.Different)
. Und Sie können sogar hinzufügen,OldValue = left.Value
wenn Sie auch den alten Wert benötigen.Ich wusste nichts über die Enumerable.SequenceEqual-Methode (Sie lernen jeden Tag etwas ...), aber ich wollte die Verwendung einer Erweiterungsmethode vorschlagen. etwas wie das:
Interessanterweise scheint Microsoft nach 2 Sekunden zum Lesen von SequenceEqual die von mir für Sie beschriebene Funktion erstellt zu haben.
quelle
Dies beantwortet Ihre Fragen nicht direkt, sondern wird sowohl von den TestTools als auch von NUnit der MS bereitgestellt
das macht so ziemlich was du willst.
quelle
Zum Vergleichen von Sammlungen können Sie auch LINQ verwenden.
Enumerable.Intersect
Gibt alle Paare zurück, die gleich sind. Sie können zwei Wörterbücher wie folgt vergleichen:Der erste Vergleich ist erforderlich, da er
dict2
alle Schlüssel vondict1
und mehr enthalten kann.Sie können auch denken Variationen verwenden Verwendung
Enumerable.Except
undEnumerable.Union
diese führen zu ähnlichen Ergebnissen. Kann aber verwendet werden, um die genauen Unterschiede zwischen Sätzen zu bestimmen.quelle
Wie wäre es mit diesem Beispiel:
Mit freundlicher Genehmigung: https://www.dotnetperls.com/dictionary-equals
quelle
Für bestellte Sammlungen (Liste, Array) verwenden
SequenceEqual
für die Verwendung von HashSet
SetEquals
Für Dictionary können Sie Folgendes tun:
(Eine optimierte Lösung verwendet Sortierung, dies erfordert jedoch
IComparable<TValue>
)quelle
Nein. Der Sammlungsrahmen hat kein Konzept der Gleichheit. Wenn Sie darüber nachdenken, gibt es keine Möglichkeit, Sammlungen zu vergleichen, die nicht subjektiv sind. Wenn Sie beispielsweise Ihre IList mit Ihrem Wörterbuch vergleichen, wären sie gleich, wenn sich alle Schlüssel in der IList, alle Werte in der IList oder beide in der IList befinden würden? Es gibt keine offensichtliche Möglichkeit, diese beiden Sammlungen zu vergleichen, ohne zu wissen, wofür sie verwendet werden sollen. Daher macht eine Methode für allgemeine Zwecke gleich keinen Sinn.
quelle
Nein, da das Framework nicht weiß, wie der Inhalt Ihrer Listen verglichen werden soll.
Schau dir das an:
http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx
quelle
IComparer<T>
, Zwingendeobject.Equals
,IEquatable<T>
,IComparable<T>
...quelle
Es gab, gibt und gibt es nicht, zumindest würde ich das glauben. Der Grund dafür ist, dass die Gleichheit der Sammlung wahrscheinlich ein benutzerdefiniertes Verhalten ist.
Elemente in Sammlungen sollten nicht in einer bestimmten Reihenfolge sein, obwohl sie natürlich eine Reihenfolge haben. Darauf sollten sich die Vergleichsalgorithmen nicht stützen. Angenommen, Sie haben zwei Sammlungen von:
Sind sie gleich oder nicht? Sie müssen wissen, aber ich weiß nicht, was Ihre Sichtweise ist.
Sammlungen sind standardmäßig konzeptionell ungeordnet, bis die Algorithmen die Sortierregeln bereitstellen. Wenn Sie versuchen, eine Paginierung durchzuführen, werden Sie auf SQL Server aufmerksam gemacht. Dazu müssen Sie Sortierregeln angeben:
https://docs.microsoft.com/en-US/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017
Noch zwei Sammlungen:
Sind sie wieder gleich oder nicht? Du sagst es mir ..
Die Wiederholbarkeit von Elementen einer Sammlung spielt in verschiedenen Szenarien eine Rolle, und einige Sammlungen
Dictionary<TKey, TValue>
erlauben nicht einmal wiederholte Elemente.Ich glaube, diese Art der Gleichstellung ist anwendungsdefiniert und der Rahmen bot daher nicht alle möglichen Implementierungen.
Nun, im Allgemeinen sind Fälle
Enumerable.SequenceEqual
gut genug, aber im folgenden Fall wird false zurückgegeben:Ich habe einige Antworten auf Fragen wie diese gelesen (Sie können sie googeln ) und was ich im Allgemeinen verwenden würde:
Das heißt, eine Sammlung repräsentiert die andere in ihren Elementen, einschließlich wiederholter Zeiten, ohne die ursprüngliche Bestellung zu berücksichtigen. Einige Hinweise zur Implementierung:
GetHashCode()
ist nur für die Bestellung nicht für die Gleichheit; Ich denke es ist genug in diesem FallCount()
wird die Sammlung nicht wirklich aufzählen und direkt in die Eigenschaftsimplementierung von fallenICollection<T>.Count
Wenn die Referenzen gleich sind, ist es nur Boris
quelle