Как разбить список на куски одинакового размера? - PullRequest
1920 голосов
/ 23 ноября 2008

У меня есть список произвольной длины, и мне нужно разделить его на куски одинакового размера и обработать его. Есть несколько очевидных способов сделать это, например, сохранить счетчик и два списка, и когда второй список заполнится, добавить его в первый список и очистить второй список для следующего раунда данных, но это потенциально чрезвычайно дорого.

Мне было интересно, есть ли у кого-нибудь хорошее решение для списков любой длины, например, используя генераторы.

Я искал что-то полезное в itertools, но не смог найти что-то полезное. Возможно, я пропустил это.

Смежный вопрос: Какой самый «питонный» способ перебрать список по частям?

Ответы [ 58 ]

7 голосов
/ 28 февраля 2015

Еще одна более явная версия.

def chunkList(initialList, chunkSize):
    """
    This function chunks a list into sub lists 
    that have a length equals to chunkSize.

    Example:
    lst = [3, 4, 9, 7, 1, 1, 2, 3]
    print(chunkList(lst, 3)) 
    returns
    [[3, 4, 9], [7, 1, 1], [2, 3]]
    """
    finalList = []
    for i in range(0, len(initialList), chunkSize):
        finalList.append(initialList[i:i+chunkSize])
    return finalList
7 голосов
/ 24 ноября 2008
def split_seq(seq, num_pieces):
    start = 0
    for i in xrange(num_pieces):
        stop = start + len(seq[i::num_pieces])
        yield seq[start:stop]
        start = stop

использование:

seq = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for seq in split_seq(seq, 3):
    print seq
7 голосов
/ 23 ноября 2008

хех, версия с одной строкой

In [48]: chunk = lambda ulist, step:  map(lambda i: ulist[i:i+step],  xrange(0, len(ulist), step))

In [49]: chunk(range(1,100), 10)
Out[49]: 
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
 [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
 [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
 [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
 [41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
 [51, 52, 53, 54, 55, 56, 57, 58, 59, 60],
 [61, 62, 63, 64, 65, 66, 67, 68, 69, 70],
 [71, 72, 73, 74, 75, 76, 77, 78, 79, 80],
 [81, 82, 83, 84, 85, 86, 87, 88, 89, 90],
 [91, 92, 93, 94, 95, 96, 97, 98, 99]]
6 голосов
/ 17 апреля 2017

Еще одно решение

def make_chunks(data, chunk_size): 
    while data:
        chunk, data = data[:chunk_size], data[chunk_size:]
        yield chunk

>>> for chunk in make_chunks([1, 2, 3, 4, 5, 6, 7], 2):
...     print chunk
... 
[1, 2]
[3, 4]
[5, 6]
[7]
>>> 
5 голосов
/ 18 февраля 2013

См. эту ссылку

>>> orange = range(1, 1001)
>>> otuples = list( zip(*[iter(orange)]*10))
>>> print(otuples)
[(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), ... (991, 992, 993, 994, 995, 996, 997, 998, 999, 1000)]
>>> olist = [list(i) for i in otuples]
>>> print(olist)
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ..., [991, 992, 993, 994, 995, 996, 997, 998, 999, 1000]]
>>> 

Python3

5 голосов
/ 03 мая 2011

Рассмотрите возможность использования matplotlib.cbook штук

например:

import matplotlib.cbook as cbook
segments = cbook.pieces(np.arange(20), 3)
for s in segments:
     print s
5 голосов
/ 04 ноября 2015

На данный момент, я думаю, нам нужна обязательная анонимно-рекурсивная функция.

Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
chunks = Y(lambda f: lambda n: [n[0][:n[1]]] + f((n[0][n[1]:], n[1])) if len(n[0]) > 0 else [])
5 голосов
/ 03 ноября 2016

Так как все здесь говорят об итераторах. boltons имеет идеальный метод для этого, называемый iterutils.chunked_iter.

from boltons import iterutils

list(iterutils.chunked_iter(list(range(50)), 11))

Выход:

[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
 [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21],
 [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32],
 [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43],
 [44, 45, 46, 47, 48, 49]]

Но если вы не хотите пощадить память, вы можете использовать old-way и вначале сохранить полный list с iterutils.chunked.

5 голосов
/ 16 июля 2015
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
CHUNK = 4
[a[i*CHUNK:(i+1)*CHUNK] for i in xrange((len(a) + CHUNK - 1) / CHUNK )]
4 голосов
/ 20 ноября 2016

Вы можете использовать функцию array_split для numpy, например, np.array_split(np.array(data), 20), чтобы разбить на 20 почти одинаковых по размеру кусков.

Чтобы убедиться, что куски в точности равны по размеру, используйте np.split.

...