2010-11-22 21 views
8

Tengo el siguiente Linq para agrupar una lista por año, luego por mes.Linq: grupo por año y mes, y administrar meses vacíos

var changesPerYearAndMonth = list 
       .GroupBy(revision => new { revision.LocalTimeStamp.Year, revision.LocalTimeStamp.Month }) 
       .Select(group => new { GroupCriteria = group.Key, Count = group.Count() }) 
       .OrderBy(x => x.GroupCriteria.Year) 
       .ThenBy(x => x.GroupCriteria.Month); 

Mi salida de corriente es la siguiente:

Year 2005, month 1, count 469 
Year 2005, month 5, count 487 
Year 2005, month 9, count 452 
Year 2006, month 1, count 412 
Year 2006, month 5, count 470 
... 

Como se puede ver, meses sin valor, no se incluyen en la consulta. Me gustaría incluirlos, que tiene la siguiente salida:

Year 2005, month 1, count 469 
Year 2005, month 2, count 0 
Year 2005, month 3, count 0 
... 
Year 2005, month 12, count 0 
Year 2006, month 1, count 412 
Year 2006, month 2, count 0 
... 
Year 2006, month 12, count 0 

En otras palabras, tengo que conseguir también meses vacías.

¿Podría implementar esto con una consulta Linq? Gracias de antemano

+2

¿por qué pasamos tanto tiempo dar con un LINQ difícil, no legible e ineficiente cuando podemos hacerlo más simple y legible en un bucle? – Aliostad

+1

@Aliostad: Hasta ahora, la solución Linq de Daniel es bastante directa y fácil de leer. Siempre puede recurrir a usar un bucle si la respuesta a esta pregunta resulta ser demasiado complicada con Linq. – Heinzi

+0

Bueno, creo que estamos en un mundo loco por Linq que no es bueno. Pierdes todo ese poder de depuración. El punto es, similar a XSLT, si se vuelve demasiado complejo, es un castillo de naipes. – Aliostad

Respuesta

18

creo que quiere algo como esto:

var changesPerYearAndMonth = 
    from year in Enumerable.Range(2005, 6) 
    from month in Enumerable.Range(1, 12) 
    let key = new { Year = year, Month = month } 
    join revision in list on key 
       equals new { revision.LocalTimeStamp.Year, 
          revision.LocalTimeStamp.Month } into g 
    select new { GroupCriteria = key, Count = g.Count() }; 

Tenga en cuenta que:

  • Es necesario saber qué años que está tratando de llegar a los datos para. Puede obtener esto de otra consulta, por supuesto, para encontrar los años mínimo y máximo involucrados - o tal vez encontrar el mínimo y asumir que no habrá nada en el futuro (no sé si esto es una suposición válida o no)
  • Esto automáticamente se ordenó correctamente
+0

Jon Skeen 1: Me 0. Pero no me gusta la parte "Necesitas saber qué años". Necesita hacer una consulta más para saber con qué años está trabajando. – Euphoric

+0

@Euphoric: voy a editar para que quede más claro. –

+0

@John: hay algunos errores en la consulta. No compila Estoy revisando ... –

Cuestiones relacionadas