Erstellen Sie ein Wörterbuch in einer Liste mit Gruppierung

106

Ich habe das folgende Objekt in einer Liste:

public class DemoClass
{
    public int GroupKey { get; set; }
    public string DemoString { get; set; }
    public object SomeOtherProperty { get; set; }
}

Jetzt möchte ich folgendes Wörterbuch daraus erstellen:

Dictionary<int, List<DemoClass>>

Ich möchte die List<DemoClass>nach der Eigenschaft gruppieren GroupKey, aber ich verstehe nicht, wie dies gemacht wird und etwas Hilfe.

Nachdem ich ein wenig nachgedacht hatte, erreichte ich das erforderliche Verhalten mit:

var groupedDemoClasses = from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                            group demoClass by demoClass.GroupKey
                            into groupedDemoClass
                            select groupedDemoClass;
var neededDictionary = groupedDemoClass.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Aber gibt es eine Möglichkeit, dies zu einer einzigen Aussage zu machen?

Andreas Niedermair
quelle

Antworten:

88
var groupedDemoClasses = (from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                          group demoClass by demoClass.GroupKey
                          into groupedDemoClass
                          select groupedDemoClass).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Dieser wird funktionieren !!!

Prashant Cholachagudda
quelle
198

Nur um den Vorschlag von mquander konkret zu machen :

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .GroupBy(x => x.GroupKey)
                             .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Sie würden es kürzer machen, wenn Sie natürlich auch kürzere Variablennamen verwenden würden :)

Könnte ich jedoch vorschlagen, dass eine Suche angemessener ist? Ein Lookup ist im Grunde ein Wörterbuch von einem Schlüssel zu einem IEnumerable<T>- wenn Sie die Werte nicht wirklich als Liste benötigen , wird der Code mit dem ToLookup- Aufruf noch kürzer (und effizienter) :

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .ToLookup(x => x.GroupKey);
Jon Skeet
quelle
1
Ich dachte, dass eine Suche im Vergleich zu einem erstellten Wörterbuch in einer Langzeitumgebung nicht so gut funktioniert, da das Ergebnis für jede Anfrage neu erstellt wird. Bitte korrigieren Sie mich, wenn ich falsch liege.
Andreas Niedermair
Nein, es wird die gesamte Suche erstellt. Im Allgemeinen verwendet ToXXX keine verzögerte Ausführung.
Jon Skeet
1
(Möglicherweise denken Sie an eine Gruppierung, die tatsächlich verschoben wird.)
Jon Skeet
1
Wenn ich nicht so boshaft wäre, würde ich dich abstimmen. Kam für den Linq, blieb für die Datenstruktur, von der ich noch nie gehört habe!
Chris McCall
2
@sasikt: Das Modell ist, dass Sie alles nachschlagen können und nur eine leere Sammlung erhalten, wenn der Schlüssel nicht vorhanden ist. Das ist oft nützlicher als der TryGetValue-Ansatz IMO.
Jon Skeet
6

Sie haben es bereits zu einem Einzeiler gemacht. Setzen Sie einfach das ToDictionaryam Ende Ihrer ersten Zeile. Wenn Sie möchten, dass es kürzer wird, verwenden Sie die Syntax der funktionalen Komposition anstelle der Abfragesyntax.

mqp
quelle
3

Ich gehe hier etwas vom Thema ab, aber ich bin zu diesem Thread gekommen, weil ich nach einer Möglichkeit gesucht habe, ein Wörterbuch eines Wörterbuchs in Linq zu erstellen, und die Konversation hier hat mich zur Antwort geführt ...

Mit linq können Sie mehrstufige Wörterbücher erstellen. Dies ist nützlich für Szenarien, in denen Sie mehr als einen Schlüssel oder eine Dimension haben, nach der Sie suchen möchten. Der Trick besteht darin, eine Gruppierung zu erstellen und diese dann wie folgt in ein Wörterbuch zu konvertieren:

  Dim qry = (From acs In ActualSales _
             Group By acs.ProductID Into Group _
             Select ProductID, Months = Group.ToDictionary(Function(c) c.Period) _
            ).ToDictionary(Function(c) c.ProductID)

Die resultierende Abfrage kann wie folgt verwendet werden:

 If qry.ContainsKey(_ProductID) Then
      With qry(_ProductID)
          If .Months.ContainsKey(_Period) Then
             ...
          End If
      End With
 End If

Ich hoffe, dies ist hilfreich für alle anderen, die diese Art von Abfrage benötigen.

Kennzeichen
quelle