.NET-Generika - Vergleichen Sie zwei Listen und filter: best practice
Habe ich zwei generische Listen des Typs T. Beide Listen enthalten die gleichen Typ, und ich möchte erstellen Sie eine Dritte Liste (oder eine gefilterte version der Liste 2) auf der Grundlage der Elemente in der Liste zwei, die nicht in Liste 1, basierend auf der ID von jedem item.
Jede Liste enthält ein "Paket" - Objekt, das die ID-Eigenschaft.
Ich jetzt verspottet, bis Sie den code mit For Each-Schleifen, die ich kenne, ist schrecklich (das Große O ist Konstante Zeit) also ich würde gerne eine weitere effiziente Methode.
dieser code in VB pro Projekt requirments, aber ich bevorzuge C# - also entweder code-Beispiel für mich arbeiten würde.
Private Sub RemoveStockPackagesFromSelection()
Dim p As Package
Dim packageList As List(Of Package) = New List(Of Package)
Dim stockPackageList As List(Of Package) = New List(Of Package)
Dim result As List(Of Package) = New List(Of Package)
' Fill list with User's Packages
For i As Integer = 0 To ListBox2.Items.Count - 1
p = New Package
p.Id = CInt(ListBox2.Items(i).Value)
p.Name = ListBox2.Items(i).Text
packageList.Add(p)
Next
' Fill list with Stock Packages to compare:
Dim ds As DataSet = DAL.GetStandardPackages()
For Each dr As DataRow In ds.Tables(0).Rows
p = New Package
p.Id = CInt(dr.Item("id"))
stockPackageList.Add(p)
Next
' Do Compare and Filter
For Each p1 As Package In packageList
For Each p2 As Package In stockPackageList
If Not p1.Id = p2.Id Then
result.Add(p2)
End If
Next
Next
' Here is our new trimmed list:
Response.Write(result.Count)
End Sub
Was ist ein schönes und sauberes LINQ oder Lamda Weg, das zu tun diese Art der Filterung? Was ist die Große O von meiner Methode und was wäre der Big O der vorgeschlagenen Methode (nur draussen meine Neugier).
Dank
- Haben Sie versucht, Ihren code? Es nicht so funktioniert, wie Sie es beschreiben sollte.
- Shawn, für eine Frage wie diese kann man auch weglassen Abfüllung der Basis-Listen. Wir glauben, Sie haben zwei Listen.
- Es gibt einige erstaunliche Antworten hier aus in erstaunlich kurzer Zeit. Ich Liebe dieses forum. Ich Baue ein Beispiel für die Verwendung von IEqualityComparer und Zebi ist LINQ-Abfrage, wie das ist, was vor allem ich war auf der Suche, aber ich appricate, die beraten, mit HashSets, Dictionaries und die .Außer () - Erweiterungsmethode. Alle sehr solide und interessante Lösungen. Ich bin versuchen zu verstehen, Big-O (das scheint zu sein, das Heiße Thema des Tages in CSE), also danke für deine Einsicht, Jungs. Super Antworten...
- Zeit (und Speicher -) Komplexität immer war und wahrscheinlich immer sein wird, ein heißes Thema in CS.
- Stimmt, Algorithmische Programmierung immer da war und immer sein wird, unabhängig davon, was neue Sprachen entstehen - Big O wird immer ein "heißes Thema". Denke, das war irgendwie eine dumme Sache zu sagen... UndoSelfDepricatingComment() 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
LINQ-Except-Methode
Wäre dies die sauberste Art und Weise, wie vorgeschlagen, von Maxim und svick erfordert aber eine überschriebene Equals-Methode gleich auf ID oder geben Sie einen comparer (siehe svicks Antwort).
Ressourcen
Viele LINQ samles finden Sie in der msdn unter http://msdn.microsoft.com/en-us/vcsharp/aa336746
Lasse ich den ersten Teil meiner Antwort verweisen:
Brute-force-Weg:
sollte den trick tun. Sie müssen nur zu übersetzen, die lambda-syntax vb.net.
Diese Abfrage filtert alle Elemente aus
stockPackageList
die IDs sind nicht alle Elemente vonpackageList
.Können Sie umkehren-Abfrage:
Den
Any
Abfrage gibt true zurück, wenn jedes Element inpackageList
mit einer passenden id. Diese Abfrage sollte etwas schneller laufen, weil es nicht um die traverse der ganzen Sammlung, wieAll
hat.Mit Eqality:
Wenn Ihr Paket-Objekt implementiert
IEquatable<Package>
Sie verkürzen den code unten, umVerwendung einer Hash-Set:
Wenn Sie möchten, verwenden Sie ein hash-set, die Sie tun können
Dies spart Rechenzeit, wenn die Listen groß geworden, als faester und Ivan Danilov hingewiesen.
Except
Methode, die Beispiele sind als Antworten zu.Kann nicht wirklich Lesen, die Sie VB-code, aber wenn Sie wollen, um die Elemente in l2, die nicht im l1 -
Ihr ein Beispiel für C# code
Ihre Methode hat die asymptotische Laufzeit von O(m*n), wo m und n sind die Größen Ihrer Sammlungen.
Sollten Sie danach Streben, für O(m lg n). Sie müssen aber natürlich suchen beide Sammlungen, aber Sie können bauen ein hashset von einem von Ihnen in O(n) und führen Sie Abfragen in O(1) im Durchschnitt, so sollten Sie eine Kopie einer Liste in ein hashset und durch die zweite sucht Werte, die in der ehemaligen.
Können Sie
Except()
:Diese übernimmt
Package
überladen hatEquals()
zu vergleichenId
s. Wenn es nicht, verwenden SieIEqualityComparer
, z.B. den von diese Antwort:Als für die Zeit, die Komplexität, die Ihre Lösung nicht korrekt funktionieren, so Komplex ist irrelevant. Die Komplexität der
Except()
ist O(N+M), denn es entsteht zunächst ein hash-set aus der ersten Sammlung (O(N)), dann versucht zu entfernen, jedes Element aus der zweiten Sammlung (O(M)) und dann gibt das Ergebnis zurück.Füllung Wörterbuch fast O(n) durch p1.Zählen. Und jede Suche ist O(1). So haben wir etwas in der Nähe von linearer Komplexität.
Dictionary
ist implementiert als hash-Tabelle.ContainsKey
ist auch "fast" einen O(1) - operationContainsKey
es muss nicht skaliert. Also, wenn die hashes sind gut - es ist O(1) - ohne 'fast'.List<T>
, ist, dass die meisten Ergänzungen sind O(1), einige von Ihnen sind O(aktuelle Größe), aber die amortisieren sich die Zeit pro Zusatz ist O(1) und so die Gesamtzeit ist O(N).