2013-05-17 13 views
6

Mam wiele przykładów, używając LINQ, jak podzielić listę na listę podrzędną zgodnie z maksimum pozycji na każdej liście. Ale w tym przypadku jestem zainteresowany nurkowaniem w podlistach przy użyciu sizembów jako wagi - mając maksymalny łączny rozmiar na liście 9mb.LINQ: Podział listy na grupy według wagi/rozmiaru

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; 

Powyższa lista powinna zostać podzielona na 3 listy. Jeśli jakieś "pliki" mają więcej niż 9 MB, powinny znajdować się na ich własnej liście.

Zrobiłem non LINQ wersję tutaj:

 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

dlaczego powinno być trzy listy jest tylko dwóch unikalnych wartości –

+0

chcesz listę doc1, listy z zmienna doc2 i listy z doc3 i doc4 osiągnąć? –

+1

Jaki jest oczekiwany wynik? –

Odpowiedz

7

można użyć tej metody:

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

Oto demo: http://ideone.com/OkXw7C

dok1 
dok2 
dok3,dok4 
+0

+1 dla czytelności, operator Sum mógł zostać zastąpiony przez lokalną sumę w przypadku problemu z wydajnością (dlaczego usunąłeś początkową odpowiedź?) –

+0

Jestem pod wrażeniem tej szybkiej odpowiedzi, ale powyższe nie używa LINQ – bluee

+0

@ vc74: Usunąłem ją tymczasowo, ponieważ wystąpił błąd. Dodałem '... lists.Add (list);' po pętli. –

0

Można korzystać z funkcji zbiorczej zrobić, grupa przez zadziała tylko przy porównywaniu wartości nie na podstawie dowolnego stanu, kiedy rozpocząć nowa grupa

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

Nie mogę tego skompilować .. – bluee

+0

@bluee, jeśli powiesz mi, że jestem błędem jestem pewien, że mogę rozwiązać problem, ale ogólny pomysł byłby taki sam. Sądzę, że było to po prostu '}' zamiast ')' na końcu –

Powiązane problemy