Crea un dizionario in un elenco con raggruppamento


106

Ho il seguente oggetto in un elenco:

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

Ora, voglio creare il seguente dizionario da esso:

Dictionary<int, List<DemoClass>>

Voglio raggruppare il List<DemoClass>per la proprietà GroupKey, ma non capisco come sia fatto e un po 'di aiuto.

Dopo aver riflettuto un po ', ho ottenuto il comportamento necessario con:

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());

ma c'è un modo per trasformare questo in una singola dichiarazione?

Risposte:


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

Questo funzionerà !!!


198

Giusto per rendere concreto il suggerimento di mquander :

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

Lo renderesti più breve se usassi anche nomi di variabili più brevi, ovviamente :)

Tuttavia, potrei suggerire che una di ricerca potrebbe essere più appropriata? Una ricerca è fondamentalmente un dizionario da una chiave a un IEnumerable<T>- a meno che tu non abbia davvero bisogno dei valori come un elenco, rende il codice ancora più breve (e più efficiente) con la chiamata ToLookup :

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .ToLookup(x => x.GroupKey);

1
ho pensato che una ricerca non funziona così bene, rispetto a un dizionario costruito, in un ambiente a lungo termine, perché crea il risultato fresco per ogni richiesta ... per favore correggimi, se sbaglio!
Andreas Niedermair

No, crea l'intera ricerca. In generale, ToXXX non utilizza l'esecuzione differita.
Jon Skeet

1
(Potresti pensare a un raggruppamento, che è effettivamente differito.)
Jon Skeet,

1
Se non fossi così dispettoso ti voterei. È venuto per il Linq, è rimasto per la struttura dati di cui non ho mai sentito parlare!
Chris McCall,

2
@sasikt: il modello è che puoi cercare qualsiasi cosa e ottieni solo una raccolta vuota se la chiave non esiste. Questo è spesso più utile dell'approccio TryGetValue, IMO.
Jon Skeet

6

Hai già creato una battuta. ToDictionaryMetti semplicemente il alla fine della tua prima riga. Se desideri che sia più breve, utilizza la sintassi della composizione funzionale invece della sintassi della query.


3

Vado leggermente fuori tema qui, ma sono arrivato a questo thread perché stavo cercando un modo per creare un dizionario di un dizionario in Linq, e la conversazione qui mi ha portato alla risposta ...

È possibile utilizzare LINQ per creare dizionari multi-livello, che è utile per gli scenari in cui hai più di 1 tasto o dimensione che si desidera cercare da. Il trucco sta nel creare un raggruppamento e poi convertirlo in un dizionario, come segue:

  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)

La query risultante può essere utilizzata come segue:

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

Spero che questo sia utile a chiunque altro abbia bisogno di questo tipo di query.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.