ILookup vs. IGrouping
Frage
Ich habe Probleme, die Unterschiede zwischen ILookup<TKey, TVal>
und IGrouping<TKey, TVal>
und neugierig ist, wenn ich es jetzt richtig verstanden. LINQ verstärkt das Problem durch Sequenzen von IGrouping
Elemente produzieren, während auch mir eine ToLookup
Erweiterungsmethode geben. So fühlte es sich wie sie die gleichen waren, bis ich näher betrachtet.
var q1 =
from n in N
group n by n.MyKey into g
select g;
// q1 is IEnumerable<IGrouping<TKey, TVal>>
Welche äquivalent zu:
var q2 = N.GroupBy(n => n.MyKey, n => n);
// q2 is IEnumerable<IGrouping<TKey, TVal>>
Welche viel wie folgt aussieht:
var q3 = N.ToLookup(n => n.MyKey, n => n);
// q3 is ILookup<TKey, TVal>
Am mich richtig in den folgenden Analogien?
- An
IGrouping<TKey, TVal>
ist eine einzelne Gruppe (das heißt eine Keyed-Sequenz), die analog zuKeyValuePair<TKey, TVal>
wo der Wert tatsächlich eine Folge von Elementen ist (und nicht als ein einzelnes Element) - Ein
IEnumerable<IGrouping<TKey, TVal>>
ist eine Folge von denen (ähnlich dem, was Sie, wenn Iterieren über eineIDictionary<TKey, TVal>
bekommen - Ein
ILookup<TKey, TVal>
ist mehr wie einIDictionary<TKey, TVal>
, wo der Wert ist eigentlich eine Folge von Elementen
Lösung
Ja, alle die sind richtig.
Und ILookup<TKey, TValue>
erstreckt sich auch IEnumerable<IGrouping<TKey, TValue>>
, so dass Sie alle auch den Schlüssel / Sammlung Paare iterieren können als (oder statt) nur bestimmte Tasten nach oben.
Ich denke, im Grunde von ILookup<TKey,TValue>
als wie IDictionary<TKey, IEnumerable<TValue>>
zu sein.
Beachten Sie, dass ToLookup
ist eine „es jetzt tun“ -Operation (sofortige Ausführung), während ein GroupBy
aufgeschoben wird. Wie es passiert, mit der Art und Weise, dass „Pull LINQ“ funktioniert, wenn Sie ziehen IGrouping
s aus dem Ergebnis eines GroupBy
beginnen, es trotzdem alle die Daten lesen hat, während in anderen Implementierungen (weil Sie nicht Gruppe auf halben Weg durch den Schalter) es kann der Lage sein, ein Streaming-Ergebnis zu erzeugen. (Es ist in LINQ Push-;. Ich würde LINQ to Events erwartet das gleiche sein)
Andere Tipps
Es ist ein weiterer wichtiger Unterschied zwischen ILookup und IDictionary: die ehemaligen Unveränderlichkeit erzwingt in dem Sinne, dass hier keine Methoden, um die Daten zu ändern (außer, wenn der Verbraucher führt eine explizite Umwandlung). Im Gegensatz dazu hat IDictionary Methoden wie „Hinzufügen“, die die Daten erlauben zu ändern. So, aus der Sicht der Funktionsprogrammierung und / oder parallel Programmierung ist ILookup schöner. (Ich wünschte nur, es gibt auch eine Version von ILookup dass Abtretungsempfänger nur ein Wert zu einem Schlüssel anstelle einer Gruppe.)
(. Btw, so scheint es erwähnenswert, dass die Beziehung zwischen IEnumerable und IList ist etwas ähnlich zu dem zwischen ILookup und IDictionary -. Die ehemaligen unveränderlich ist, letztere nicht)
GroupBy
und ToLookUp
fast gleiche Funktionalität hat außer folgt aus: Referenz
GroupBy: Die GroupBy Zurückgegeben Gruppen von Elementen auf einige Basis Schlüsselwert. Jede Gruppe wird dargestellt durch IGrouping Objekt.
ToLookup: ToLookup ist die gleiche wie GroupBy; Der einzige Unterschied die Ausführung GroupBy wird abgegrenzt, während der Ausführung ist ToLookup sofort.
Hier können deaktivieren Sie die Differenz mit Beispielcode. nehme an, dass wir eine Klasse repräsentieren Person
Modell haben:
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 personnels
von ihrem Niveau gruppiert bekommen. Ich hier zwei Ansatz haben. mit GroupBy
oder ToLookUp
. Wenn ich GroupBy
verwenden, wie bereits erwähnt, wird es verzögerte Ausführung verwenden, bedeutet dies, dass, wenn Sie Iteration durch die Auflistung der nächste Punkt kann oder nicht berechnet werden, bis sie benötigt werden.
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);
}
In dem obigen Code, ich zunächst die personnels
gruppiert, aber bevor es iterieren, entfernte ich einige personnels
. Als GroupBy
Anwendungen verzögerte Ausführung, so wird das Endergebnis nicht die entfernten Elemente enthalten, da die Gruppierung wird hier im foreach
Punkt wird berechnet wird.
Ausgabe:
2
2 >>> P2 >>> 2
5 >>> P5 >>> 2
6 >>> P6 >>> 2
7 >>> P7 >>> 2
Aber wenn ich den obigen Code umschreiben wie folgt: (beachten Sie, dass Code gleiche ist wie der vorherige Code außer GroupBy
durch ToLookUp
ersetzt wird)
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);
}
Als ToLookUp
sofortige Ausführung verwendet, so bedeutet dies, dass, wenn ich die ToLookUp
Methode aufrufen, Ergebnis erzeugt wird, und Gruppe angewendet wird, so dass, wenn I vor der Iteration jedes Element aus personnels
entfernen, dass gewohnt Wirkung 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
und ToLookUp
beide Rückkehr verschiedene Arten zu
Sie könnten ToDictionary anstelle von ToLookup, aber Sie müssen darauf achten, diese: ( Referenz )
Die Verwendung von ToLookup (), die der ToDictionary sehr ähnlich ist (), beide können Sie Schlüsselschalter, Wert Selektoren angeben, und comparers. Der Hauptunterschied besteht darin, dass ToLookup () ermöglicht (und erwartet) der doppelte Schlüssel während ToDictionary () nicht