2013-05-17 14 views
6

Ho molti esempi che utilizzano LINQ come dividere un elenco in un sotto-elenco in base alle voci massime in ciascuna lista. Ma in questo caso sono interessato a immergere una sotto-lista usando sizemb come un peso - avendo un file totale massimo per lista di 9mb.LINQ: Dividi l'elenco in gruppi in base al peso/dimensione

public class doc 
    { 
     public string file; 
     public int sizemb; 
    } 

    var list = new List<doc>() 
    { 
     new doc { file = "dok1", sizemb = 5 }, 
     new doc { file = "dok2", sizemb = 5 }, 
     new doc { file = "dok3", sizemb = 5 }, 
     new doc { file = "dok4", sizemb = 4 }, 
    }; 

    int maxTotalFileSize = 9; 

L'elenco precedente deve essere diviso in 3 elenchi. Se alcuni "file" sono più di 9mb dovrebbero essere nella loro lista.

Ho fatto una LINQ-versione non qui:

 var lists = new List<List<doc>>(); 
     foreach (var item in list) 
     { 
      //Try and place the document into a sub-list 
      var availableSlot = lists.FirstOrDefault(p => (p.Sum(x => x.sizemb) + item.sizemb) < maxGroupSize); 
      if (availableSlot == null) 
       lists.Add(new List<doc>() { item }); 
      else 
       availableSlot.Add(item); 
     } 
+0

perché dovrebbe essere tre liste ci sono solo due valori unici –

+0

si vuole raggiungere con la lista doc1, la lista con doc2 e la lista con doc3 e doc4? –

+1

Qual è il risultato previsto ?? –

risposta

7

Si potrebbe utilizzare questo metodo:

IEnumerable<IList<doc>> SplitDocumentList(IEnumerable<doc> allDocuments, int maxMB) 
{ 
    var lists = new List<IList<doc>>(); 
    var list = new List<doc>(); 
    foreach (doc document in allDocuments) 
    { 
     int totalMB = list.Sum(d => d.sizemb) + document.sizemb; 
     if (totalMB > maxMB) 
     { 
      lists.Add(list); 
      list = new List<doc>(); 
     } 
     list.Add(document); 
    } 
    if (list.Count > 0) 
     lists.Add(list); 
    return lists; 
} 

Ecco una demo: http://ideone.com/OkXw7C

dok1 
dok2 
dok3,dok4 
+0

+1 per la leggibilità, l'operatore Sum potrebbe essere sostituito da una variabile di somma locale in caso di problemi di prestazioni (perché hai eliminato la tua risposta iniziale?) –

+0

Sono impressionato da questa risposta veloce, ma quanto sopra non sta realmente utilizzando LINQ – bluee

+0

@ vc74: l'ho eliminato temporaneamente poiché c'era un bug. Ho aggiunto il '... lists.Add (elenco);' dopo il ciclo. –

0

È possibile utilizzare la funzione di aggregazione per farlo, il gruppo da funziona solo quando si confrontano i valori non in base a una condizione arbitraria di quando iniziare un nuovo gruppo

list.Aggregate(new List<List<doc>>(), (acc,d) => { 
      if(acc.last().Sum(x => x.sizemb) + d.sizemb > 9) { 
       acc.Add(new List<doc>()); 
      } 
      acc.last().Add(d); 
      return acc; 
    } 
) 
+1

Non riesco a ottenere questo per compilare .. – bluee

+0

@bluee se mi dici l'errore che sto sicuro di poter risolvere il problema ma l'idea generale sarebbe la stessa. Suppongo che fosse semplicemente '}' invece di a ')' alla fine –

Problemi correlati