У меня есть список произвольной длины, и мне нужно разделить его на куски одинакового размера и обработать его. Есть несколько очевидных способов сделать это, например, сохранить счетчик и два списка, и, когда второй список заполнится, добавить его в первый список и очистить второй список для следующего раунда данных, но это потенциально чрезвычайно дорого.
Мне было интересно, есть ли у кого-нибудь хорошее решение для списков любой длины, например, используя генераторы.
Я искал что-то полезное в itertools
, но не смог найти ничего явно полезного. Возможно, я пропустил это.
Смежный вопрос: Какой самый «питонный» способ перебрать список по частям?
с использованием списка пониманий Python
[range(t,t+10) for t in range(1,1000,10)]
[[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],....
....[981, 982, 983, 984, 985, 986, 987, 988, 989, 990],
[991, 992, 993, 994, 995, 996, 997, 998, 999, 1000]]
посетите эту ссылку , чтобы узнать о списках
Я знаю, что это довольно старо, но я не знаю, почему никто не упомянул numpy.array_split
:
lst = range(50)
In [26]: np.array_split(lst,5)
Out[26]:
[array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),
array([20, 21, 22, 23, 24, 25, 26, 27, 28, 29]),
array([30, 31, 32, 33, 34, 35, 36, 37, 38, 39]),
array([40, 41, 42, 43, 44, 45, 46, 47, 48, 49])]
import pprint pprint.pprint(list(chunks(range(10, 75), 10))) [range(10, 20), range(20, 30), range(30, 40), range(40, 50), range(50, 60), range(60, 70), range(70, 75)]
Сопоставьте результат этой реализации с примером результата использования принятого ответа . sup>
Многие из вышеперечисленных функций предполагают, что длина всей итерируемой заранее известна или, по крайней мере, является дешевой для вычисления.
Для некоторых потоковых объектов это означало бы сначала загрузку полных данных в память (например, загрузку всего файла) для получения информации о длине.
Если вы еще не знаете полный размер, вы можете использовать этот код вместо этого:
def chunks(iterable, size):
"""
Yield successive chunks from iterable, being `size` long.
https://stackoverflow.com/a/55776536/3423324
:param iterable: The object you want to split into pieces.
:param size: The size each of the resulting pieces should have.
"""
i = 0
while True:
sliced = iterable[i:i + size]
if len(sliced) == 0:
# to suppress stuff like `range(max, max)`.
break
# end if
yield sliced
if len(sliced) < size:
# our slice is not the full length, so we must have passed the end of the iterator
break
# end if
i += size # so we start the next chunk at the right place.
# end while
# end def
Это работает, потому что команда slice вернет меньше / нет элементов, если вы передали конец итерируемый:
"abc"[0:2] == 'ab'
"abc"[2:4] == 'c'
"abc"[4:6] == ''
Теперь мы используем этот результат среза и вычисляем длину этого сгенерированного фрагмента. Если это меньше, чем мы ожидаем, мы знаем, что можем закончить итерацию.
Таким образом, итератор не будет выполняться без доступа.
У меня есть одно решение ниже, которое работает, но более важным, чем это решение, является несколько комментариев о других подходах. Во-первых, хорошее решение не должно требовать, чтобы один цикл проходил через итераторы по порядку. Если я запускаю
g = paged_iter(list(range(50)), 11))
i0 = next(g)
i1 = next(g)
list(i1)
list(i0)
Соответствующим выводом для последней команды будет
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
, а не
[]
, поскольку здесь возвращается большинство решений на основе itertools. Это не просто обычное скучное ограничение доступа к итераторам по порядку. Представьте себе, что потребитель пытается очистить плохо введенные данные, которые поменяли местами соответствующий порядок блоков, равный 5, т.е. данные выглядят как [B5, A5, D5, C5] и должны выглядеть как [A5, B5, C5, D5] (где А5 это всего лишь пять элементов, а не подсписок). Этот потребитель посмотрит на заявленное поведение функции группировки и без колебаний напишет цикл, подобный
i = 0
out = []
for it in paged_iter(data,5)
if (i % 2 == 0):
swapped = it
else:
out += list(it)
out += list(swapped)
i = i + 1
. Это приведет к загадочно неверным результатам, если вы будете хитро предполагать, что субитераторы всегда полностью используются по порядку. Это становится еще хуже, если вы хотите чередовать элементы из кусков.
Во-вторых, приличное количество предложенных решений неявно основывается на том факте, что итераторы имеют детерминированный порядок (например, они не установлены), и хотя некоторые решения, использующие islice, могут быть в порядке, меня это беспокоит.
В-третьих, подход группирования itertools работает, но рецепт опирается на внутреннее поведение функций zip_longest (или zip), которое не является частью их опубликованного поведения. В частности, функция группирования работает только потому, что в zip_longest (i0 ... in) следующая функция всегда вызывается в следующем порядке (i0), next (i1), ... next (in) перед началом заново. Когда группер передает n копий одного и того же объекта итератора, он полагается на это поведение.
Наконец, хотя решение, приведенное ниже, может быть улучшено, если вы критикуете вышеизложенное предположение о том, что к субтераторам обращаются по порядку и полностью просматривается без этого допущения, он ДОЛЖЕН неявно (через цепочку вызовов) или явно (через запросы или другую структуру данных). ) хранить элементы для каждого подтератора где-нибудь. Так что не тратьте время (как я), предполагая, что можно обойти это с помощью некоторого умного трюка.
def paged_iter(iterat, n):
itr = iter(iterat)
deq = None
try:
while(True):
deq = collections.deque(maxlen=n)
for q in range(n):
deq.append(next(itr))
yield (i for i in deq)
except StopIteration:
yield (i for i in deq)
Вот список дополнительных подходов:
Дан
import itertools as it
import collections as ct
import more_itertools as mit
iterable = range(11)
n = 3
Код
Стандартная библиотека
list(it.zip_longest(*[iter(iterable)] * n))
# [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]
d = {}
for i, x in enumerate(iterable):
d.setdefault(i//n, []).append(x)
list(d.values())
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
dd = ct.defaultdict(list)
for i, x in enumerate(iterable):
dd[i//n].append(x)
list(dd.values())
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
more_itertools
+ sup>
list(mit.chunked(iterable, n))
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
list(mit.sliced(iterable, n))
# [range(0, 3), range(3, 6), range(6, 9), range(9, 11)]
list(mit.grouper(n, iterable))
# [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]
list(mit.windowed(iterable, len(iterable)//n, step=n))
# [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]
Список литературы
zip_longest
( связанный пост , соответствующий пост ) setdefault
(упорядоченные результаты требуют Python 3.6 +) collections.defaultdict
(упорядоченные результаты требуют Python 3.6 +) more_itertools.chunked
( связанный пост ) more_itertools.sliced
more_itertools.grouper
( соответствующий пост ) more_itertools.windowed
(см. Также stagger
, zip_offset
) + sup> Сторонняя библиотека, в которой реализованы рецепты itertools и другие. > pip install more_itertools
Если бы у вас был размер чанка, например, 3, вы могли бы сделать:
zip(*[iterable[i::3] for i in range(3)])
источник: http://code.activestate.com/recipes/303060-group-a- list-in-sequential-n-tuples /
Я бы использовал это, когда размер моего чанка равен фиксированному числу, которое я могу напечатать, например «3», и никогда не изменится.
На данный момент, я думаю, нам нужен рекурсивный генератор , на всякий случай ...
В питоне 2:
def chunks(li, n):
if li == []:
return
yield li[:n]
for e in chunks(li[n:], n):
yield e
В питоне 3:
def chunks(li, n):
if li == []:
return
yield li[:n]
yield from chunks(li[n:], n)
Кроме того, в случае массового вторжения инопланетян, рекурсивный генератор, украшенный , может стать . удобно:
def dec(gen):
def new_gen(li, n):
for e in gen(li, n):
if e == []:
return
yield e
return new_gen
@dec
def chunks(li, n):
yield li[:n]
for e in chunks(li[n:], n):
yield e
Мне очень нравится версия документа Python, предложенная tzot и JFSebastian, но у нее есть два недостатка:
Я часто использую это в своем коде:
from itertools import islice
def chunks(n, iterable):
iterable = iter(iterable)
while True:
yield tuple(islice(iterable, n)) or iterable.next()
ОБНОВЛЕНИЕ: версия ленивых чанков:
from itertools import chain, islice
def chunks(n, iterable):
iterable = iter(iterable)
while True:
yield chain([next(iterable)], islice(iterable, n-1))
Да, это старый вопрос, но я должен был опубликовать этот, потому что он даже немного короче похожих. Да, результат выглядит зашифрованным, но если он примерно равен длине ...
>>> n = 3 # number of groups
>>> biglist = range(30)
>>>
>>> [ biglist[i::n] for i in xrange(n) ]
[[0, 3, 6, 9, 12, 15, 18, 21, 24, 27],
[1, 4, 7, 10, 13, 16, 19, 22, 25, 28],
[2, 5, 8, 11, 14, 17, 20, 23, 26, 29]]
Я видел самый удивительный ответ на языке Python в дубликате этого вопроса:
from itertools import zip_longest
a = range(1, 16)
i = iter(a)
r = list(zip_longest(i, i, i))
>>> print(r)
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12), (13, 14, 15)]
Вы можете создать n-кортеж для любого n. Если a = range(1, 15)
, то результатом будет:
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12), (13, 14, None)]
Если список разделен равномерно, то вы можете заменить zip_longest
на zip
, в противном случае триплет (13, 14, None)
будет потерян. Python 3 используется выше. Для Python 2 используйте izip_longest
.
Никакой магии, но простой и правильный:
def chunks(iterable, n):
"""Yield successive n-sized chunks from iterable."""
values = []
for i, item in enumerate(iterable, 1):
values.append(item)
if i % n == 0:
yield values
values = []
if values:
yield values
def split(arr, size):
L = len(arr)
assert 0 < size <= L
s, r = divmod(L, size)
t = s + 1
a = ([arr[p:p+t] for p in range(0, r*t, t)] + [arr[p:p+s] for p in range(r*t, L, s)])
return a
по мотивам http://wordaligned.org/articles/slicing-a-list-evenly-with-python
Если вы знаете размер списка:
def SplitList(mylist, chunk_size):
return [mylist[offs:offs+chunk_size] for offs in range(0, len(mylist), chunk_size)]
Если вы не знаете (итератор):
def IterChunks(sequence, chunk_size):
res = []
for item in sequence:
res.append(item)
if len(res) >= chunk_size:
yield res
res = []
if res:
yield res # yield the last, incomplete, portion
В последнем случае его можно перефразировать в более красивой форме. Кстати, если вы можете быть уверены, что последовательность всегда содержит целое количество фрагментов заданного размера (т. е. нет неполного последнего фрагмента).
Вы можете использовать Dask, чтобы разбить список на куски одинакового размера. Dask имеет дополнительное преимущество сохранения памяти, которое лучше всего подходит для очень больших данных. Для достижения наилучших результатов вы должны загрузить свой список непосредственно в dask-фрейм данных, чтобы сохранить память, если ваш список очень большой. В зависимости от того, что именно вы хотите сделать со списками, Dask имеет полный API-интерфейс функций, которые вы можете использовать: http://docs.dask.org/en/latest/dataframe-api.html
import pandas as pd
import dask.dataframe as dd
split = 4
my_list = range(100)
df = dd.from_pandas(pd.DataFrame(my_list), npartitions = split)
my_list = [ df.get_partition(n).compute().iloc[:,0].tolist() for n in range(split) ]
# [[1,2,3,..],[26,27,28...],[51,52,53...],[76,77,78...]]
код:
def split_list(the_list, chunk_size):
result_list = []
while the_list:
result_list.append(the_list[:chunk_size])
the_list = the_list[chunk_size:]
return result_list
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print split_list(a_list, 3)
результат:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
Вы также можете использовать функцию get_chunks
библиотеки utilspie
как:
>>> from utilspie import iterutils
>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(iterutils.get_chunks(a, 5))
[[1, 2, 3, 4, 5], [6, 7, 8, 9]]
Вы можете установить utilspie
через пункт:
sudo pip install utilspie
Отказ от ответственности: Я являюсь создателем библиотеки utilspie .
Мне было интересно узнать о производительности различных подходов, и вот оно:
Проверено на Python 3.5.1
import time
batch_size = 7
arr_len = 298937
#---------slice-------------
print("\r\nslice")
start = time.time()
arr = [i for i in range(0, arr_len)]
while True:
if not arr:
break
tmp = arr[0:batch_size]
arr = arr[batch_size:-1]
print(time.time() - start)
#-----------index-----------
print("\r\nindex")
arr = [i for i in range(0, arr_len)]
start = time.time()
for i in range(0, round(len(arr) / batch_size + 1)):
tmp = arr[batch_size * i : batch_size * (i + 1)]
print(time.time() - start)
#----------batches 1------------
def batch(iterable, n=1):
l = len(iterable)
for ndx in range(0, l, n):
yield iterable[ndx:min(ndx + n, l)]
print("\r\nbatches 1")
arr = [i for i in range(0, arr_len)]
start = time.time()
for x in batch(arr, batch_size):
tmp = x
print(time.time() - start)
#----------batches 2------------
from itertools import islice, chain
def batch(iterable, size):
sourceiter = iter(iterable)
while True:
batchiter = islice(sourceiter, size)
yield chain([next(batchiter)], batchiter)
print("\r\nbatches 2")
arr = [i for i in range(0, arr_len)]
start = time.time()
for x in batch(arr, batch_size):
tmp = x
print(time.time() - start)
#---------chunks-------------
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
print("\r\nchunks")
arr = [i for i in range(0, arr_len)]
start = time.time()
for x in chunks(arr, batch_size):
tmp = x
print(time.time() - start)
#-----------grouper-----------
from itertools import zip_longest # for Python 3.x
#from six.moves import zip_longest # for both (uses the six compat library)
def grouper(iterable, n, padvalue=None):
"grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
return zip_longest(*[iter(iterable)]*n, fillvalue=padvalue)
arr = [i for i in range(0, arr_len)]
print("\r\ngrouper")
start = time.time()
for x in grouper(arr, batch_size):
tmp = x
print(time.time() - start)
Результаты:
slice
31.18285083770752
index
0.02184295654296875
batches 1
0.03503894805908203
batches 2
0.22681021690368652
chunks
0.019841909408569336
grouper
0.006506919860839844
[AA[i:i+SS] for i in range(len(AA))[::SS]]
Где AA - массив, SS - размер фрагмента. Например:
>>> AA=range(10,21);SS=3
>>> [AA[i:i+SS] for i in range(len(AA))[::SS]]
[[10, 11, 12], [13, 14, 15], [16, 17, 18], [19, 20]]
# or [range(10, 13), range(13, 16), range(16, 19), range(19, 21)] in py3
heh, одна версия строки
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]]
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
На данный момент, я думаю, нам нужна обязательная анонимно-рекурсивная функция.
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 [])
Так как все здесь говорят об итераторах. 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
.
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 )]
Ни один из этих ответов не является кусками одинакового размера, все они оставляют кусочек в конце, поэтому они не полностью сбалансированы. Если бы вы использовали эти функции для распределения работы, вы встроили перспективу того, что одна из них, вероятно, закончится задолго до других, поэтому она будет сидеть сложа руки, ничего не делая, в то время как другие продолжат усердно работать.
Например, текущий верхний ответ заканчивается:
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]
Я просто ненавижу этот ворчать в конце!
Другие, такие как list(grouper(3, xrange(7)))
и chunk(xrange(7), 3)
, оба возвращают : [(0, 1, 2), (3, 4, 5), (6, None, None)]
. None
просто набивают, и, на мой взгляд, довольно неэлегантно. Они НЕ равномерно разбивают фрагменты.
Почему мы не можем разделить их лучше?
Вот сбалансированное решение, адаптированное из функции, которую я использовал в производстве (Примечание в Python 3 для замените xrange
на range
):
def baskets_from(items, maxbaskets=25):
baskets = [[] for _ in xrange(maxbaskets)] # in Python 3 use range
for i, item in enumerate(items):
baskets[i % maxbaskets].append(item)
return filter(None, baskets)
И я создал генератор, который сделает то же самое, если вы поместите его в список:
def iter_baskets_from(items, maxbaskets=3):
'''generates evenly balanced baskets from indexable iterable'''
item_count = len(items)
baskets = min(item_count, maxbaskets)
for x_i in xrange(baskets):
yield [items[y_i] for y_i in xrange(x_i, item_count, baskets)]
И, наконец, так как я видим, что все вышеперечисленные функции возвращают элементы в непрерывном порядке (как они были заданы):
def iter_baskets_contiguous(items, maxbaskets=3, item_count=None):
'''
generates balanced baskets from iterable, contiguous contents
provide item_count if providing a iterator that doesn't support len()
'''
item_count = item_count or len(items)
baskets = min(item_count, maxbaskets)
items = iter(items)
floor = item_count // baskets
ceiling = floor + 1
stepdown = item_count % baskets
for x_i in xrange(baskets):
length = ceiling if x_i < stepdown else floor
yield [items.next() for _ in xrange(length)]
Чтобы проверить их:
print(baskets_from(xrange(6), 8))
print(list(iter_baskets_from(xrange(6), 8)))
print(list(iter_baskets_contiguous(xrange(6), 8)))
print(baskets_from(xrange(22), 8))
print(list(iter_baskets_from(xrange(22), 8)))
print(list(iter_baskets_contiguous(xrange(22), 8)))
print(baskets_from('ABCDEFG', 3))
print(list(iter_baskets_from('ABCDEFG', 3)))
print(list(iter_baskets_contiguous('ABCDEFG', 3)))
print(baskets_from(xrange(26), 5))
print(list(iter_baskets_from(xrange(26), 5)))
print(list(iter_baskets_contiguous(xrange(26), 5)))
Что распечатывает:
[[0], [1], [2], [3], [4], [5]]
[[0], [1], [2], [3], [4], [5]]
[[0], [1], [2], [3], [4], [5]]
[[0, 8, 16], [1, 9, 17], [2, 10, 18], [3, 11, 19], [4, 12, 20], [5, 13, 21], [6, 14], [7, 15]]
[[0, 8, 16], [1, 9, 17], [2, 10, 18], [3, 11, 19], [4, 12, 20], [5, 13, 21], [6, 14], [7, 15]]
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14], [15, 16, 17], [18, 19], [20, 21]]
[['A', 'D', 'G'], ['B', 'E'], ['C', 'F']]
[['A', 'D', 'G'], ['B', 'E'], ['C', 'F']]
[['A', 'B', 'C'], ['D', 'E'], ['F', 'G']]
[[0, 5, 10, 15, 20, 25], [1, 6, 11, 16, 21], [2, 7, 12, 17, 22], [3, 8, 13, 18, 23], [4, 9, 14, 19, 24]]
[[0, 5, 10, 15, 20, 25], [1, 6, 11, 16, 21], [2, 7, 12, 17, 22], [3, 8, 13, 18, 23], [4, 9, 14, 19, 24]]
[[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]]
Обратите внимание, что непрерывный генератор обеспечивает фрагменты в тех же шаблонах длины, что и два других, но все элементы расположены по порядку, и они разделены настолько равномерно, что можно разделить список дискретных элементов.
Еще одно решение
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]
>>>
Попробуйте использовать matplotlib.cbook штук
, например:
import matplotlib.cbook as cbook
segments = cbook.pieces(np.arange(20), 3)
for s in segments:
print s
Если вы хотите что-то очень простое:
def chunks(l, n):
n = max(1, n)
return (l[i:i+n] for i in xrange(0, len(l), n))
Используйте range()
вместо xrange()
в случае Python 3.x
Без вызова len (), что хорошо для больших списков:
def splitter(l, n):
i = 0
chunk = l[:n]
while chunk:
yield chunk
i += n
chunk = l[i:i+n]
И это для итераций:
def isplitter(l, n):
l = iter(l)
chunk = list(islice(l, n))
while chunk:
yield chunk
chunk = list(islice(l, n))
Функциональная разновидность вышеупомянутого:
def isplitter2(l, n):
return takewhile(bool,
(tuple(islice(start, n))
for start in repeat(iter(l))))
ИЛИ:
def chunks_gen_sentinel(n, seq):
continuous_slices = imap(islice, repeat(iter(seq)), repeat(0), repeat(n))
return iter(imap(tuple, continuous_slices).next,())
ИЛИ:
def chunks_gen_filter(n, seq):
continuous_slices = imap(islice, repeat(iter(seq)), repeat(0), repeat(n))
return takewhile(bool,imap(tuple, continuous_slices))
Еще одна более явная версия.
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
См. эту ссылку
>>> 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
.