2009-08-11 13 views
7

KONTEKST

  • Mam listę elementów (lub dowolnej długości). Chciałbym pogrupować je w "porcje" o określonym rozmiarze.
  • Przykład: mam 12 klientów [0,1,2,3,4,5,6,7,8,9,10,11] oraz chcesz zgrupować kawałki min wynoszące 5, co dałoby [0,1,2,3,4] [5,6,7,8,9] [10,11]
  • UWAGA: W rzeczywistości nie pracuję z klientami lub monotonicznie rosnące liczby całkowite. Wybrałem to tylko uproszczenie zadać pytanie

moje pytanie

Jak mogę sformułować proste kwerendy LINQ (przy użyciu składni zapytań), który wykonuje tego ugrupowania?LINQ: Jak grupy przez maksymalną liczbę elementów

TŁO

  • jestem już pewny, jak używać składni LINQ do grupowania według wartości na przykład (do sprzedaży grupowych przez ID klienta), jednak jestem w rozterce, jak Wyrażając „wyrwy "czyściutko/elegancko za pomocą LINQ. Nie jestem pewien, czy jest to możliwe w prosty sposób.
  • Mogę i już zaimplementowałem rozwiązanie w plain-old-C# bez użycia składni LINQ. Tak więc, mój problem nie jest blokowany w tym pytaniu, ale raczej szukam sposobów na wyrażenie go w LINQ (znowu czyściutko i elegancko).
+0

możliwe duplikat [lista podzielonych na podlist Linq] (http://stackoverflow.com/questions/419019/split-list-into -sublists-with-linq) – nawfal

Odpowiedz

9

Można je grupować według (index/chunkSize). Przykład:

var result = 
     from i in array.Select((value, index) => new { Value = value, Index = index }) 
     group i.Value by i.Index/chunkSize into g 
     select g; 
+1

Jest to jeden z tych rzadkich przypadków, gdy zwykła pętla i słownik są krótsze ORAZ bardziej zrozumiałe niż LINQ ... – Ray

+0

@Dimitriy - dziękuję za odpowiedź @Ray - zdecydowanie – namenlos

+0

Ładne rozwiązanie ! Bardzo pomocne! –

2

Dla tych, którzy preferują metody LINQ (z wyrażeń lambda), tutaj jest Dimitriy Matveev's answer przekształcone:

var result = array 
    .Select((value, index) => new { Value = value, Index = index }) 
    .GroupBy(i => i.Index/chunkSize, v => v.Value); 

Jeśli potrzebujesz tylko tablicę value, zamiast IGrouping<T1, T2>, a następnie dołączyć następujące:

.Select(x => x.ToArray()) 
0

Aby zrobić rzeczywiste ugrupowania, nie powinno to być:

var result = array 
.Select((value, index) => new { Value = value, Index = index}) 
.GroupBy(i => i.Index/chunk, v => v.Value); 
+0

Steven - masz rację. Zaktualizowałem swoją odpowiedź. Dzięki za złapanie tego. Zwróć też uwagę, że StackOverflow (StackExchange jako całość) nie jest stylem forum, w którym odpowiadasz na "powyższą" odpowiedź. Postanowiłeś odpowiedzieć na to pytanie. Rozumiem, że prawdopodobnie nie masz wystarczającej liczby przedstawicieli, aby dodać komentarz. Tak więc, po prostu próbuję pomóc. – Jesse

0

metodę rozszerzenia (stosując Jesse's answer)

public static IEnumerable<T[]> GroupToChunks<T>(this IEnumerable<T> items, int chunkSize) 
{ 
    if (chunkSize <= 0) 
    { 
     throw new ArgumentException("Chunk size must be positive.", "chunkSize"); 
    } 

    return 
     items.Select((item, index) => new { item, index }) 
      .GroupBy(pair => pair.index/chunkSize, pair => pair.item) 
      .Select(grp => grp.ToArray()); 
} 
Powiązane problemy