2009-01-14 12 views
21

¿Cómo crearía una agrupación anidada para la siguiente tabla, utilizando LINQ? Quiero agrupar por Code, luego por Mktcode.¿Cómo creo un grupo anidado por diccionario usando LINQ?

Code Mktcode Id 
==== ======= ==== 
1 10  0001 
2 20  0010 
1 10  0012 
1 20  0010 
1 20  0014 
2 20  0001 
2 30  0002 
1 30  0002 
1 30  0005 

Me gustaría un diccionario, al final, al igual que

Dictionary<Code, List<Dictionary<Mktcode, List<Id>>>> 

Así que los valores de este diccionario sería

{1, ({10,(0001,0012)}, {20,(0010,0014)}, {30, (0002, 0005)})}, 
{2, ({20,(0001, 0010)}, {30, (0020)})} 

Respuesta

26

yo creo que de esta manera:

  • Estás principalmente agrupar por código, por lo que la primera
  • Para cada grupo, todavía tienes una lista de resultados - por lo que aplicar otro agrupando allí.

Algo así como:

var groupedByCode = source.GroupBy(x => x.Code); 

var groupedByCodeAndThenId = groupedByCode.Select(group => 
    new { Key=group.Key, NestedGroup = group.ToLookup 
             (result => result.MktCode, result => result.Id)); 

var dictionary = groupedByCodeAndThenId.ToDictionary 
    (result => result.Key, result => result.NestedGroup); 

que le dará un Dictionary<Code, Lookup<MktCode, Id>> - yo creo eso es lo que quiere. Sin embargo, no ha sido probado.

+5

Vaya, estás muy bien. Tu poder mental es simplemente increíble. – Graviton

16

Usted puede construir Búsquedas de (tipos de diccionario < , Lista < >>) usando group by into

var lines = new [] 
{ 
    new {Code = 1, MktCode = 10, Id = 1}, 
    new {Code = 2, MktCode = 20, Id = 10}, 
    new {Code = 1, MktCode = 10, Id = 12}, 
    new {Code = 1, MktCode = 20, Id = 10}, 
    new {Code = 1, MktCode = 20, Id = 14}, 
    new {Code = 2, MktCode = 20, Id = 1}, 
    new {Code = 2, MktCode = 30, Id = 2}, 
    new {Code = 1, MktCode = 30, Id = 2}, 
    new {Code = 1, MktCode = 30, Id = 5}, 
}; 

var groups = from line in lines 
    group line by line.Code 
    into codeGroup 
    select new 
    { 
     Code = codeGroup.Key, 
     Items = from l in codeGroup 
      group l by l.MktCode into mktCodeGroup 
      select new 
      { 
       MktCode = mktCodeGroup.Key, 
       Ids = from mktLine in mktCodeGroup 
        select mktLine.Id 
      } 
    }; 
+0

¿Alguna idea sobre cómo convertir grupos a tipo de diccionario? – Graviton

+5

groups.ToDictionary (g => g.Key, g => g.ToList()) –

12

Así es como yo lo haría:

Dictionary<Code, Dictionary<MktCode, List<Id>>> myStructure = 
    myList 
    .GroupBy(e => e.Code) 
    .ToDictionary(
     g => g.Key, 
     g => g 
     .GroupBy(e => e.Mktcode) 
     .ToDictionary(
      g2 => g2.Key, 
      g2 => g2.Select(e => e.Id).ToList() 
     ) 
    ) 

Aquí está la ruptura del proceso:

agrupar los elementos de código, y crear un diccionario de afuera, donde la clave es que el código.

myList 
    .GroupBy(e => e.Code) 
    .ToDictionary(
     g => g.Key, 

Para cada una de las teclas en el diccionario exterior, se reagrupan los elementos por Mktcode y crear un diccionario interior.

 g => g 
     .GroupBy(e => e.Mktcode) 
     .ToDictionary(
      g2 => g2.Key, 

Para cada una de las claves en el diccionario interno, proyecte la identificación de esos elementos y conviértala en una lista.

  g2 => g2.Select(e => e.Id).ToList() 
     ) 
    ) 
+1

Este es el que yo entiendo. ¡Gracias! – orad

Cuestiones relacionadas