2009-08-11 7 views
7

CONTEXTE

  • J'ai une liste d'éléments (ou longueur arbitraire). Je voudrais les regrouper en «morceaux» d'une certaine taille
  • Exemple: J'ai 12 clients [0,1,2,3,4,5,6,7,8,9,10,11] et vouloir les regrouper en morceaux de 5 qui donneraient [0,1,2,3,4] [5,6,7,8,9] [10,11]
  • NOTE: En réalité, je ne travaille pas avec les clients ou des nombres entiers croissant de façon monotone. Je pris cela juste pour simplifier poser la question

MA QUESTION

Comment puis-je formuler une requête LINQ simple (en utilisant la syntaxe de requête) qui exécute ce groupe?Linq: Comment le groupe par le nombre maximum d'éléments

CONTEXTE

  • Je suis déjà familier avec la façon d'utiliser la syntaxe LINQ pour le regroupement d'une valeur par exemple (pour les ventes du groupe par numéro de client), mais je suis à une perte comment exprimer la « Chunking 'proprement/élégamment en utilisant LINQ. Je ne suis pas sûr si c'est même possible d'une manière simple.
  • Je peux et ai déjà implémenté une solution en plain-old-C# sans utiliser la syntaxe LINQ. Ainsi, mon problème n'est pas bloqué sur cette question, mais plutôt je cherche des manières de l'exprimer dans LINQ (encore proprement et élégamment)
+0

double possible de [Liste Divisé en sous-listes avec LINQ] (http://stackoverflow.com/questions/419019/split-list-into -sublists-with-linq) – nawfal

Répondre

9

Vous pouvez les grouper par (index/chunkSize). Exemple:

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

Ceci est l'un de ces cas rares où un simple pour la boucle et un dictionnaire est plus court et plus compréhensible que LINQ ... – Ray

+0

@Dimitriy - merci pour la réponse @Ray - certainement – namenlos

+0

Belle solution ! Très utile! –

2

Pour ceux qui préfèrent les méthodes LINQ (avec des expressions lambda), voici Dimitriy Matveev's answer converti:

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

Si vous avez juste besoin d'un tableau de value, au lieu d'un IGrouping<T1, T2>, puis ajouter les éléments suivants:

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

Pour faire le regroupement réel, devrait-il pas:

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

Steven - vous avez raison. J'ai mis à jour ma réponse. Merci d'avoir attrapé ça. Notez également que StackOverflow (StackExchange dans son ensemble) n'est pas un style de forum, où vous répondez à la réponse "above". Vous avez posé pour répondre à la question. Je réalise que vous n'avez probablement pas assez de rep pour ajouter un commentaire. Donc, de toute façon, essayant juste d'aider. – Jesse

0

méthode d'extension (en utilisant 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()); 
} 
Questions connexes