Как разбить список на куски одинакового размера?

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

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

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

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

1958
задан Community 23 May 2017 в 11:55
поделиться

60 ответов

с использованием списка пониманий 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]]

посетите эту ссылку , чтобы узнать о списках

-1
ответ дан BomberMan 23 May 2017 в 11:55
поделиться

Я знаю, что это довольно старо, но я не знаю, почему никто не упомянул 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])]
153
ответ дан Moj 23 May 2017 в 11:55
поделиться

Ленивая загрузка версии

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)]

Сопоставьте результат этой реализации с примером результата использования принятого ответа .

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

Для некоторых потоковых объектов это означало бы сначала загрузку полных данных в память (например, загрузку всего файла) для получения информации о длине.

Если вы еще не знаете полный размер, вы можете использовать этот код вместо этого:

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] == ''

Теперь мы используем этот результат среза и вычисляем длину этого сгенерированного фрагмента. Если это меньше, чем мы ожидаем, мы знаем, что можем закончить итерацию.

Таким образом, итератор не будет выполняться без доступа.

0
ответ дан luckydonald 23 May 2017 в 11:55
поделиться

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

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)
3
ответ дан Peter Gerdes 23 May 2017 в 11:55
поделиться

Вот список дополнительных подходов:

Дан

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 +

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)]

Список литературы

+ Сторонняя библиотека, в которой реализованы рецепты itertools и другие. > pip install more_itertools

5
ответ дан pylang 23 May 2017 в 11:55
поделиться

Если бы у вас был размер чанка, например, 3, вы могли бы сделать:

zip(*[iterable[i::3] for i in range(3)]) 

источник: http://code.activestate.com/recipes/303060-group-a- list-in-sequential-n-tuples /

Я бы использовал это, когда размер моего чанка равен фиксированному числу, которое я могу напечатать, например «3», и никогда не изменится.

16
ответ дан ninjagecko 23 May 2017 в 11:55
поделиться

На данный момент, я думаю, нам нужен рекурсивный генератор , на всякий случай ...

В питоне 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
12
ответ дан mazieres 23 May 2017 в 11:55
поделиться

Мне очень нравится версия документа 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))
14
ответ дан nikipore 23 May 2017 в 11:55
поделиться

Да, это старый вопрос, но я должен был опубликовать этот, потому что он даже немного короче похожих. Да, результат выглядит зашифрованным, но если он примерно равен длине ...

>>> 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]]
-2
ответ дан koffein 23 May 2017 в 11:55
поделиться

Я видел самый удивительный ответ на языке 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.

34
ответ дан Ioannis Filippidis 23 May 2017 в 11:55
поделиться

Никакой магии, но простой и правильный:

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
2
ответ дан guyskk 23 May 2017 в 11:55
поделиться
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

-2
ответ дан Adeojo Emmanuel IMM 23 May 2017 в 11:55
поделиться

Если вы знаете размер списка:

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

В последнем случае его можно перефразировать в более красивой форме. Кстати, если вы можете быть уверены, что последовательность всегда содержит целое количество фрагментов заданного размера (т. е. нет неполного последнего фрагмента).

24
ответ дан cardamom 23 May 2017 в 11:55
поделиться

Вы можете использовать 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...]]
0
ответ дан N.Bell 23 May 2017 в 11:55
поделиться

код:

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]]
11
ответ дан buhtz 23 May 2017 в 11:55
поделиться

Вы также можете использовать функцию 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 .

11
ответ дан Moinuddin Quadri 23 May 2017 в 11:55
поделиться

Мне было интересно узнать о производительности различных подходов, и вот оно:

Проверено на 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
11
ответ дан Alex T 23 May 2017 в 11:55
поделиться
[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
10
ответ дан Riaz Rizvi 23 May 2017 в 11:55
поделиться

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]]
7
ответ дан slav0nic 23 May 2017 в 11:55
поделиться
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
ответ дан Corey Goldberg 23 May 2017 в 11:55
поделиться

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

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
ответ дан Julien Palard 23 May 2017 в 11:55
поделиться

Так как все здесь говорят об итераторах. 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
ответ дан vishes_shell 23 May 2017 в 11:55
поделиться
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 )]
5
ответ дан AdvilUser 23 May 2017 в 11:55
поделиться

Критика других ответов здесь:

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

Например, текущий верхний ответ заканчивается:

[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]]

Обратите внимание, что непрерывный генератор обеспечивает фрагменты в тех же шаблонах длины, что и два других, но все элементы расположены по порядку, и они разделены настолько равномерно, что можно разделить список дискретных элементов.

32
ответ дан Aaron Hall 23 May 2017 в 11:55
поделиться

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

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]
>>> 
6
ответ дан Анатолий Панин 23 May 2017 в 11:55
поделиться

Попробуйте использовать matplotlib.cbook штук

, например:

import matplotlib.cbook as cbook
segments = cbook.pieces(np.arange(20), 3)
for s in segments:
     print s
5
ответ дан schwartrer 23 May 2017 в 11:55
поделиться

Если вы хотите что-то очень простое:

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

517
ответ дан Satya 23 May 2017 в 11:55
поделиться

Без вызова 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))
7
ответ дан parity3 23 May 2017 в 11:55
поделиться

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

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
ответ дан Ranaivo 23 May 2017 в 11:55
поделиться

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

>>> 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
ответ дан BomberMan 23 May 2017 в 11:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: