2010-11-22 10 views
8

Ho il seguente Linq per raggruppare un elenco per anno, poi per mese.Linq: gruppo per anno e mese, e gestire i mesi vuoti

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

La mia uscita di corrente è il seguente:

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 
... 

Come si può vedere, i mesi senza valore, non sono incluse nella query. Mi piacerebbe includerli, avente la seguente uscita:

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 

In altre parole, ho bisogno di ottenere anche mesi vuoti.

È possibile implementarlo con una query Linq? Grazie in anticipo

+2

Perché spendiamo così tanto tempo a venire su con un difficile, non leggibile e inefficiente Linq quando possiamo farlo più semplice e più leggibile in un ciclo? – Aliostad

+1

@Aliostad: Finora, la soluzione di Linq di Daniel è abbastanza semplice e leggibile. Può sempre ricorrere all'utilizzo di un ciclo se la risposta a questa domanda risulta troppo complicata utilizzando Linq. – Heinzi

+0

Beh, penso che siamo in un mondo folle di Linq che non va bene. Perderai tutto quel potere di debugging. Il punto è, simile a XSLT, se diventa troppo complesso è un castello di carte. – Aliostad

risposta

18

Penso che si desidera qualcosa di simile:

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

Nota che:

  • Hai bisogno di sapere quali anni si sta cercando di venire con i dati relativi. Puoi recuperarlo da un'altra query, ovviamente, per trovare gli anni minimi e massimi coinvolti - o forse trovare il minimo e assumere che non ci sarà nulla in futuro (non so se questo sia un presupposto valido o meno)
  • Questo verrà automaticamente ordinato correttamente
+0

Jon Skeen 1: Me 0. Ma non mi piace la parte "Devi sapere che anni". Devi fare un'altra domanda per sapere con che anni stai lavorando. – Euphoric

+0

@Euforico: modificherò per renderlo più chiaro. –

+0

@John: ci sono alcuni errori nella query. Non viene compilato. Sto rivedendo ... –

Problemi correlati