2011-04-08 8 views
9

Tengo una lista con alrededor de 190 elementos por el momento. ¿Cómo puedo dividir la lista en listas más pequeñas con un máximo de 50 elementos en cada lista?¿Cómo divido una lista basada en el índice en C#?

El resultado podría ser listas de 50, 50, 50 y 40 elementos.

+0

posible duplicado de la [Lista de Split en sublistas con LINQ] (http://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq) – psubsee2003

Respuesta

20

Suponiendo que se refiere a List<T>, puede utilizar el método GetRange repetidamente. Heck, usted podría hacer esto con LINQ:

var lists = Enumerable.Range(0, (list.Count + size - 1)/size) 
     .Select(index => list.GetRange(index * size, 
            Math.Min(size, list.Count - index * size))) 
     .ToList(); 

O usted podría utilizar un bucle, por supuesto:

public static List<List<T>> Split(List<T> source, int size) 
{ 
    // TODO: Prepopulate with the right capacity 
    List<List<T>> ret = new List<List<T>>(); 
    for (int i = 0; i < source.Count; i += size) 
    { 
     ret.Add(source.GetRange(i, Math.Min(size, source.Count - i))); 
    } 
    return ret; 
} 

Esto es algo más eficaz que utilizar GroupBy, aunque se limita a List<T> como una entrada.

Tenemos otra implementación usando IEnumerable<T> en MoreLINQ en Batch.cs.

+2

@Downvoter: el cuidado de explicar? –

+0

Histórico: nunca vi a Jon, ni siquiera un segundo, en -1. Preguntaré en su lugar: ¿le importaría explicar al votante negativo? -> y, por supuesto, él me golpeó a ese :-) – Peter

+1

@Jon, no he votado negativamente, pero creo que se debió al último ejemplo. –

10

Se podría utilizar LINQ:

var list = Enumerable.Range(1, 190); 
var sublists = list 
    .Select((x, i) => new { Index = i, Value = x }) 
    .GroupBy(x => x.Index/50) 
    .Select(x => x.Select(v => v.Value).ToList()) 
    .ToArray(); 
+0

Gracias por su sugerencia, pero el foreach de Jon es simplemente más limpio. – Awesome

+0

+1: Me gusta este debido a su naturaleza declarativa – Peter

0
var list = new List<int>(Enumerable.Range(1,190)); 
var page_size = 50; 
var max_pages = 1 + list.Count()/page_size; 

for(int page = 1; page <= max_pages; page++) { 
    var chunk = list.Skip(page_size * (page-1)).Take(page_size); 
    // do whatever 
} 
1

He intentado un enfoque recursivo. Solo para ver cómo se vería.

List<List<T>> SplitIntoChunks<T>(IEnumerable<T> originalList, int chunkSize) 
{ 
    if(originalList.Take(1).Count() == 0) 
    { 
     return new List<List<T>>(); 
    } 

    var chunks = new List<List<T>> {originalList.Take(chunkSize).ToList()}; 
    chunks.AddRange(SplitIntoChunks(originalList.Skip(chunkSize), chunkSize)); 
    return chunks; 
} 
Cuestiones relacionadas