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?

  1. An IGrouping<TKey, TVal> ist eine einzelne Gruppe (das heißt eine Keyed-Sequenz), die analog zu KeyValuePair<TKey, TVal> wo der Wert tatsächlich eine Folge von Elementen ist (und nicht als ein einzelnes Element)
  2. Ein IEnumerable<IGrouping<TKey, TVal>> ist eine Folge von denen (ähnlich dem, was Sie, wenn Iterieren über eine IDictionary<TKey, TVal> bekommen
  3. Ein ILookup<TKey, TVal> ist mehr wie ein IDictionary<TKey, TVal>, wo der Wert ist eigentlich eine Folge von Elementen
War es hilfreich?

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 IGroupings 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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top