Raggruppa LINQ in un oggetto dizionario


161

Sto cercando di utilizzare LINQ per creare un Dictionary<string, List<CustomObject>>da a List<CustomObject>. Posso farlo funzionare usando "var", ma non voglio usare tipi anonimi. Ecco quello che ho

var x = (from CustomObject o in ListOfCustomObjects
      group o by o.PropertyName into t
      select t.ToList());

Ho anche provato a utilizzare Cast<>()dalla libreria LINQ una volta che ho x, ma ottengo problemi di compilazione per l'effetto di essere un cast non valido.


Che cosa succede se si prova var x = (da CustomObject o nel gruppo ListOfCustomObjects o da o.PropertyName in t selezionare t) .ToList ();
esastincy,

44
C'è qualche motivo per cui è necessario farlo piuttosto che utilizzare ToLookup, che è progettato per questo?
Jon Skeet,

1
Jon, potresti per favore pubblicare un esempio di come funziona ToLookup in questa situazione? Non ho familiarità con quel metodo LINQ.
Atari2600,

8
@JonSkeet Sei fantastico! (Voglio dire, lo sapevano già tutti, ma comunque.) Il motivo per cui non avevo intenzione di usare ToLookup era perché non ne avevo mai sentito parlare fino ad ora. Adesso lo so!
neminem,

1
Solo per completezza, usando varnon si usa un tipo "anonimo", si usa un tipo "implicito". I tipi anonimi sono nuove classi create dal compilatore per gestire la costruzione new { thing = "stuff" };. I tipi impliciti sono classi esistenti, varè solo un modo conveniente per fare riferimento a loro quando la variabile viene assegnata immediatamente, il tipo di variabile può essere dedotto dal tipo di oggetto assegnato. Puoi anche digitare in modo implicito una variabile che fa riferimento a un tipo anonimo, ovvero:var a = new { thing = "stuff" };
Michael Blackburn,

Risposte:


351
Dictionary<string, List<CustomObject>> myDictionary = ListOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToDictionary(g => g.Key, g => g.ToList());

6
A meno che tu non abbia bisogno di una proprietà di 'CustomObject' come valore dell'elenco (non mostrato in questa risposta) vale la pena controllare il suo commento di Jon Skeet alla domanda che consiglia ToLookup ().
Shaun,

3
questo è il modo di farlo se si desidera un risultato non immutabile. ToLookup è immutabile.
Entro il

1
I miei 2 centesimi (solo perché mi ha fatto lottare per un'ora :)): quando si raggruppa per una proprietà, assicurarsi che la proprietà abbia un valore! Altrimenti il ​​metodo Todict non riesce a generare la chiave (almeno per String-Properties ...) :)
dba

.GroupBy(o => o.PropertyName).ToDictionary(g => g.Key, g => g.ToList())Questa potrebbe essere una parte della libreria di estensione Linq. quindi non ci resta che fare.ToDictionary(o=>o.PropertyName)
Jaider

3
@Jaider, esiste già tale funzionalità: basta sostituirla ToDictionarycon ToLookup.
Robert Synoradzki,

19

Non posso commentare @Michael Blackburn, ma suppongo che tu abbia ottenuto il downvote perché GroupBy non è necessario in questo caso.

Usalo come:

var lookupOfCustomObjects = listOfCustomObjects.ToLookup(o=>o.PropertyName);
var listWithAllCustomObjectsWithPropertyName = lookupOfCustomObjects[propertyName]

Inoltre, l'ho visto funzionare in modo migliore rispetto all'uso di GroupBy (). ToDictionary ().


Stavo eseguendo una traslitterazione, non rispondendo alla domanda nel miglior modo possibile.
Michael Blackburn,

1

Per @ atari2600, ecco come sarebbe la risposta usando ToLookup nella sintassi lambda:

var x = listOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToLookup(customObject => customObject);

Fondamentalmente, prende IGrouping e lo materializza per te in un dizionario di elenchi, con i valori di PropertyName come chiave.


Perché un downvote? Non è accurato / rispondere alla domanda?
Michael Blackburn,

1
Nel caso in cui tu l'abbia perso, nella sua risposta @RuudvK ha affermato che sospetta che il downvote sia dovuto al fatto che GroupBy non è necessario. ToLookupha un sovraccarico che porterà a termine il lavoro.
Jeff B,

Ho perso quella risposta, grazie per avermi taggato. Ha senso, il raggruppamento è sintatticamente inutile, lo stavo lasciando solo per rendere più chiara la transizione dalla sintassi della query alla sintassi del metodo.
Michael Blackburn,

GroupBy (il sovraccarico con un solo parametro) restituisce un IEnumerable <IGrouping <TKey, TSource >> il ToLookup successivo quindi lo trasforma in un tipo abbastanza complicato che non è nemmeno simile a un IDictionary <TKey, IList <TSource>> solo il ToLookup restituisce il tipo corretto.
xtofs,

-1

Quanto segue ha funzionato per me.

var temp = ctx.Set<DbTable>()
  .GroupBy(g => new { g.id })
  .ToDictionary(d => d.Key.id);
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.