Ich hatte Probleme, die Unterschiede zwischen ILookup<TKey, TVal>
und zu artikulieren IGrouping<TKey, TVal>
, und bin gespannt, ob ich es jetzt richtig verstehe. LINQ verschärfte das Problem, indem es Sequenzen von IGrouping
Elementen produzierte und mir gleichzeitig eine ToLookup
Erweiterungsmethode gab. Es fühlte sich so an, als wären sie gleich, bis ich genauer hinschaute.
var q1 =
from n in N
group n by n.MyKey into g
select g;
// q1 is IEnumerable<IGrouping<TKey, TVal>>
Welches ist gleichbedeutend mit:
var q2 = N.GroupBy(n => n.MyKey, n => n);
// q2 is IEnumerable<IGrouping<TKey, TVal>>
Was sehr ähnlich aussieht:
var q3 = N.ToLookup(n => n.MyKey, n => n);
// q3 is ILookup<TKey, TVal>
Bin ich in den folgenden Analogien richtig?
- An
IGrouping<TKey, TVal>
ist eine einzelne Gruppe (dh eine Schlüsselfolge), analog dazu,KeyValuePair<TKey, TVal>
wo der Wert tatsächlich eine Folge von Elementen ist (und nicht ein einzelnes Element). - An
IEnumerable<IGrouping<TKey, TVal>>
ist eine Folge von diesen (ähnlich dem, was Sie erhalten, wenn Sie über ein iterierenIDictionary<TKey, TVal>
- An
ILookup<TKey, TVal>
ist eher wie a,IDictionary<TKey, TVal>
wobei der Wert tatsächlich eine Folge von Elementen ist
Es gibt einen weiteren wichtigen Unterschied zwischen ILookup und IDictionary: Ersteres erzwingt Unveränderlichkeit in dem Sinne, dass hier keine Methoden zum Ändern der Daten vorhanden sind (außer wenn der Verbraucher eine explizite Umwandlung durchführt). Im Gegensatz dazu verfügt IDictionary über Methoden wie "Hinzufügen", mit denen die Daten geändert werden können. Aus der Perspektive der funktionalen Programmierung und / oder parallelen Programmierung ist ILookup also besser. (Ich wünschte nur, es gäbe auch eine Version von ILookup, die einem Schlüssel statt einer Gruppe nur einen Wert zuweist.)
(Übrigens scheint es erwähnenswert zu sein, dass die Beziehung zwischen IEnumerable und IList der zwischen ILookup und IDictionary etwas ähnlich ist - die erstere ist unveränderlich, die letztere nicht.)
quelle
ILookup
, die nur einen Einzelwert anstelle einer Gruppe hat? Das ist was einDictionary
ist - oder einReadOnlyDictionary
oderIReadOnlyDictionary
wenn du willst, dass es unveränderlich ist.GroupBy
undToLookUp
hat fast die gleiche Funktionalität, AUSSER dies: ReferenzLassen Sie uns den Unterschied anhand des Beispielcodes beseitigen. Angenommen, wir haben eine Klasse, die das
Person
Modell darstellt:class Personnel { public int Id { get; set; } public string FullName { get; set; } public int Level { get; set; } }
Danach definieren wir eine Liste von
personnels
wie folgt:var personnels = new List<Personnel> { new Personnel { Id = 1, FullName = "P1", Level = 1 }, new Personnel { Id = 2, FullName = "P2", Level = 2 }, new Personnel { Id = 3, FullName = "P3", Level = 1 }, new Personnel { Id = 4, FullName = "P4", Level = 1 }, new Personnel { Id = 5, FullName = "P5", Level =2 }, new Personnel { Id = 6, FullName = "P6", Level = 2 }, new Personnel { Id = 7, FullName = "P7", Level = 2 } };
Jetzt muss ich die nach
personnels
ihrem Level gruppieren. Ich habe hier zwei Ansätze. mitGroupBy
oderToLookUp
. Wenn ichGroupBy
, wie bereits erwähnt, die verzögerte Ausführung verwende, bedeutet dies, dass beim Durchlaufen der Sammlung das nächste Element möglicherweise berechnet wird oder nicht, bis es angefordert wird.var groups = personnels.GroupBy(p => p.Level); personnels.RemoveAll(p => p.Level == 1); foreach (var product in groups) { Console.WriteLine(product.Key); foreach (var item in product) Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level); }
Im obigen Code habe ich zuerst die gruppiert
personnels
, aber bevor ich sie iterierte, habe ich einige entferntpersonnels
. DaGroupBy
die verzögerte Ausführung verwendet wird, enthält das Endergebnis nicht die entfernten Elemente, da die Gruppierung in der berechnet wirdforeach
Stelle berechnet wird.Ausgabe:
2 2 >>> P2 >>> 2 5 >>> P5 >>> 2 6 >>> P6 >>> 2 7 >>> P7 >>> 2
Aber wenn ich den obigen Code wie folgt umschreibe: (Beachten Sie, dass der Code mit dem vorherigen Code identisch
GroupBy
ist, außer dass er durch ersetzt wird.ToLookUp
)var groups = personnels.ToLookup(p => p.Level); personnels.RemoveAll(p => p.Level == 1); foreach (var product in groups) { Console.WriteLine(product.Key); foreach (var item in product) Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level); }
Wenn
ToLookUp
dieToLookUp
Methode sofort ausgeführt wird, bedeutet dies, dass beim Aufrufen der Methode ein Ergebnis generiert und eine Gruppe angewendet wird. Wenn ich also ein Element aus entfernepersonnels
vor der Iteration Auswirkungen auf das Endergebnis.Ausgabe:
1 1 >>> P1 >>> 1 3 >>> P3 >>> 1 4 >>> P4 >>> 1 2 2 >>> P2 >>> 2 5 >>> P5 >>> 2 6 >>> P6 >>> 2 7 >>> P7 >>> 2
Hinweis:
GroupBy
undToLookUp
beide geben auch unterschiedliche Typen zurück.Sie können ToDictionary anstelle von ToLookUp verwenden, müssen jedoch Folgendes beachten: ( Referenz )
quelle