Crea un diccionario en una lista con agrupación

106

Tengo el siguiente objeto en una lista:

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

Ahora, quiero crear el siguiente diccionario a partir de él:

Dictionary<int, List<DemoClass>>

Quiero agruparlos List<DemoClass>por propiedad GroupKey, pero no entiendo cómo se hace y algo de ayuda.

Después de pensar un poco, logré el comportamiento necesario 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());

pero, ¿hay alguna manera de convertir esto en una sola declaración?

Andreas Niedermair
fuente

Respuestas:

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

¡Este funcionará!

Prashant Cholachagudda
fuente
198

Solo para hacer concreta la sugerencia de mquander :

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

Lo acortaría si también usara nombres de variable más cortos, por supuesto :)

Sin embargo, puedo sugerir que un búsqueda podría ser más apropiada? Una búsqueda es básicamente un diccionario de una clave a una IEnumerable<T>, a menos que realmente necesite los valores como una lista, hace que el código sea aún más corto (y más eficiente) con la llamada ToLookup :

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .ToLookup(x => x.GroupKey);
Jon Skeet
fuente
1
Pensé que una búsqueda no funciona tan bien, en comparación con un diccionario construido, en un entorno de largo plazo, debido a que genera el resultado fresco para cada solicitud ... ¡corríjame si me equivoco!
Andreas Niedermair
No, crea la búsqueda completa. En general, ToXXX no usa ejecución diferida.
Jon Skeet
1
(Es posible que esté pensando en una agrupación, que de hecho está diferida.)
Jon Skeet
1
Si no fuera tan rencoroso, te votaría. ¡Vine por Linq, me quedé por la estructura de datos de la que nunca había oído hablar!
Chris McCall
2
@sasikt: El modelo es que puedes buscar cualquier cosa y obtienes una colección vacía si la clave no existe. Eso a menudo es más útil que el enfoque TryGetValue, en mi opinión.
Jon Skeet
6

Ya lo hiciste en una sola línea. Simplemente coloque ToDictionaryal final de su primera línea. Si desea que sea más corto, use la sintaxis de composición funcional en lugar de la sintaxis de consulta.

mqp
fuente
3

Me estoy saliendo un poco del tema aquí, pero llegué a este hilo porque estaba buscando una manera de crear un diccionario de un diccionario en Linq, y la conversación aquí me llevó a la respuesta ...

Usted puede utilizar LINQ para crear diccionarios de varios niveles, lo cual es útil para situaciones en las que tenemos más de 1 llave o dimensión que desea realizar la búsqueda. El truco consiste en crear una agrupación y luego convertirla en un diccionario, de la siguiente manera:

  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 consulta resultante se puede utilizar de la siguiente manera:

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

Espero que esto sea útil para cualquier otra persona que necesite este tipo de consulta.

marca
fuente