Mam listę dowolnej długości i muszę podzielić go na równe kawałki i działać na nim. Istnieją pewne oczywiste sposoby, aby to zrobić, jak utrzymywanie licznika i dwóch list, a gdy druga lista się wypełnia, dodaj go do pierwszej listy i opróżnić drugą listę dla następnej rundy danych, ale jest to potencjalnie bardzo drogie.

Zastanawiałem się, czy ktoś miał dobre rozwiązanie dla wykazów jakiejkolwiek długości, np. za pomocą generatorów.

Szukałem czegoś przydatnego w itertools, ale nie mogłem znaleźć niczego oczywiście przydatne. Jednak jednak by tego przegapił.

Powiązane pytanie: Co to jest Większość "Pythonic" droga do itera na liście na kawałki?

2460
jespern 23 listopad 2008, 15:15

29 odpowiedzi

Jeszcze jedno rozwiązanie

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
Анатолий Панин 19 grudzień 2017, 10:27

W tym momencie myślę, że potrzebujemy obowiązkowej funkcji anonimowej rekurencyjnej.

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 4 listopad 2015, 09:12

Jeśli chcesz czegoś bardzo prostego:

def chunks(l, n):
    n = max(1, n)
    return (l[i:i+n] for i in range(0, len(l), n))

Użyj xrange() zamiast range() w przypadku Python 2.x

584
Roelant 6 styczeń 2020, 10:56

Bezpośrednio z (starej) dokumentacji Python (Przepisy dla Itertools):

from itertools import izip, chain, repeat

def grouper(n, iterable, padvalue=None):
    "grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
    return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)

Aktualna wersja, jak sugerowana przez j.f.Sebastian:

#from itertools import izip_longest as zip_longest # for Python 2.x
from itertools import zip_longest # for Python 3.x
#from six.moves import zip_longest # for both (uses the six compat library)

def grouper(n, iterable, padvalue=None):
    "grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
    return zip_longest(*[iter(iterable)]*n, fillvalue=padvalue)

Zgaduję, że maszyna czasowa Guido pracuje - będzie pracować - będzie pracował - znów pracował.

Te rozwiązania działają, ponieważ [iter(iterable)]*n (lub odpowiednik w wcześniejszej wersji) tworzy jeden iterator, powtarzane n razy na liście. izip_longest Następnie skutecznie wykonuje okrągły robinę "każdego" iteratora; Ponieważ jest to ten sam iterator, jest ono zaawansowany przez każde takie połączenie, co skutkuje każdemu takim zip-roundrobin generowania jednej krotki n.

310
tzot 21 wrzesień 2017, 09:47

Wiem, że to rodzaj starego, ale nikt jeszcze nie wspomniał {{x0} }:

import numpy as np

lst = range(50)
np.array_split(lst, 5)
# [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])]
271
Georgy 14 październik 2019, 08:16

Jestem zaskoczony, że nikt nie pomyślał o użyciu {x0}} 's Dwukrotnie Forma:

from itertools import islice

def chunk(it, size):
    it = iter(it)
    return iter(lambda: tuple(islice(it, size)), ())

Próbny:

>>> list(chunk(range(14), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13)]

Działa to z dowolnym narzędziami i wytwarza wyprowadzenie Lazily. Zwraca skórki, a nie iteratorzy, ale myślę, że ma jednak pewną elegancję. To też nie pad; Jeśli chcesz wypełnić, wystarczy prosta zmienność:

from itertools import islice, chain, repeat

def chunk_pad(it, size, padval=None):
    it = chain(iter(it), repeat(padval))
    return iter(lambda: tuple(islice(it, size)), (padval,) * size)

Próbny:

>>> list(chunk_pad(range(14), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, None)]
>>> list(chunk_pad(range(14), 3, 'a'))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 'a')]

Podobnie jak rozwiązania oparte na izip_longest, powyższe klocki zawsze . O ile mi wiadomo, nie ma żadnej lub dwulinowej itertools receptura dla funkcji, która ewentualnie ewentualnie klocki. Łącząc powyższe dwa podejścia, ten jest dość blisko:

_no_padding = object()

def chunk(it, size, padval=_no_padding):
    if padval == _no_padding:
        it = iter(it)
        sentinel = ()
    else:
        it = chain(iter(it), repeat(padval))
        sentinel = (padval,) * size
    return iter(lambda: tuple(islice(it, size)), sentinel)

Próbny:

>>> list(chunk(range(14), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13)]
>>> list(chunk(range(14), 3, None))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, None)]
>>> list(chunk(range(14), 3, 'a'))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 'a')]

Uważam, że jest to najkrótszy Proponowany przez Chunker, który oferuje opcjonalne wyściółki.

Jak Tomasz Gandor zaobserwowany, dwa wyściółki są nieoczekiwanie zatrzymane, jeśli napotkają długą sekwencję wartości padów. Oto ostatnia zmiana, która działa wokół tego problemu w rozsądnym sposobie:

_no_padding = object()
def chunk(it, size, padval=_no_padding):
    it = iter(it)
    chunker = iter(lambda: tuple(islice(it, size)), ())
    if padval == _no_padding:
        yield from chunker
    else:
        for ch in chunker:
            yield ch if len(ch) == size else ch + (padval,) * (size - len(ch))

Próbny:

>>> list(chunk([1, 2, (), (), 5], 2))
[(1, 2), ((), ()), (5,)]
>>> list(chunk([1, 2, None, None, 5], 2, None))
[(1, 2), (None, None), (5, None)]
186
senderle 17 listopad 2018, 01:16

Oto generator, który pracuje nad dowolnymi iterables:

def split_seq(iterable, size):
    it = iter(iterable)
    item = list(itertools.islice(it, size))
    while item:
        yield item
        item = list(itertools.islice(it, size))

Przykład:

>>> import pprint
>>> pprint.pprint(list(split_seq(xrange(75), 10)))
[[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],
 [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]]
100
ThiefMaster 17 wrzesień 2012, 21:22
def chunk(input, size):
    return map(None, *([iter(input)] * size))
54
ThiefMaster 17 wrzesień 2012, 21:22

Prosty, ale elegancki

l = range(1, 1000)
print [l[x:x+10] for x in xrange(0, len(l), 10)]

Lub jeśli wolisz:

chunks = lambda l, n: [l[x: x+n] for x in xrange(0, len(l), n)]
chunks(l, 10)
54
Corman 2 czerwiec 2020, 11:54

Krytyka innych odpowiedzi tutaj:

Żadna z tych odpowiedzi nie jest równomierna wielkości kawałków, wszyscy zostawiają poręcz na końcu, więc nie są całkowicie zrównoważone. Jeśli korzystałeś z tych funkcji, aby dystrybuować pracę, wbudowałeś - w perspektywie jednego prawdopodobnego kończącego się przed innymi, więc usiąść w pobliżu nic, podczas gdy inni kontynuowali pracę ciężko.

Na przykład bieżąca odpowiedź kończy się z:

[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]

Po prostu nienawidzę, że na końcu!

Inne, jak list(grouper(3, xrange(7))) i chunk(xrange(7), 3) oba powrócić: [(0, 1, 2), (3, 4, 5), (6, None, None)]. None są tylko wyściółki, a raczej nie jest moim zdaniem. Nie są równomiernie chatając iterables.

Dlaczego nie możemy lepiej podzielić?

Moje rozwiązania

Oto zrównoważony roztwór, przystosowany z funkcji, którego używałem w produkcji (uwaga w Pythonie 3, aby zastąpić xrange za pomocą 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) 

I stworzyłem generator, który robi to samo, jeśli umieścisz go na listę:

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

I wreszcie, ponieważ widzę, że wszystkie powyższe funkcje zwracają elementy w sposób ciągły (jak zostały dodane):

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

Wynik

Przetestować je:

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

Który drukuje:

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

Zauważ, że ciągły generator zapewnia kawałki w tych samych wzorach długości, ponieważ pozostałe dwa, ale przedmioty są w porządku, i są równie podzielone, jak można podzielić listę dyskretnych elementów.

42
Aaron Hall 24 styczeń 2021, 04:42

Widziałem najbardziej niesamowitą odpowiedź python-ish w duplikat tego pytania:

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

Możesz utworzyć n-tuple dla dowolnego n. Jeśli a = range(1, 15), wówczas wynik:

[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12), (13, 14, None)]

Jeśli lista zostanie podzielona równomiernie, możesz zastąpić zip_longest za pomocą zip, w przeciwnym razie triplet (13, 14, None) zostanie utracona. Python 3 jest używany powyżej. Dla Pythona 2, użyj izip_longest.

41
Ioannis Filippidis 21 czerwiec 2017, 13:36

Jeśli znasz rozmiar listy:

def SplitList(mylist, chunk_size):
    return [mylist[offs:offs+chunk_size] for offs in range(0, len(mylist), chunk_size)]

Jeśli nie (iterator):

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

W tym drugim przypadku można go przeformułować w piękniejszy sposób, jeśli możesz być pewien, że sekwencja zawsze zawiera całą liczbę kawałków danego rozmiaru (tj. Nie ma niekompletnego ostatniego kawałka).

39
cardamom 18 kwiecień 2019, 11:18

Jeśli miałeś na przykład rozmiar fragmentu 3, możesz zrobić:

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

Źródło: http://code.activestate.com/recipes/303060-group. -A-LIST-INFORMATE-N-TUPPS /

Używałbym tego, gdy mój rozmiar fragmentu jest stały numer, który mogę wpisać, np. "3" i nigdy się nie zmieni.

21
ninjagecko 19 kwiecień 2011, 05:27

DELZZ biblioteka ma dla tego funkcję partition:

from toolz.itertoolz.core import partition

list(partition(2, [1, 2, 3, 4]))
[(1, 2), (3, 4)]
20
zach 20 listopad 2013, 20:55
[AA[i:i+SS] for i in range(len(AA))[::SS]]

Gdzie macierz AA, SS jest wielkością fragmentu. Na przykład:

>>> 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
20
Riaz Rizvi 16 grudzień 2015, 21:42

Lubię wersję Pythona Doc Proponited przez Tzot i J.F.Sebastian, ale ma dwa niedociągnięcia:

  • Nie jest bardzo wyraźny
  • Zwykle nie chcę wartości wypełnienia w ostatnim kawałku

Używam tego dużo w moim kodzie:

from itertools import islice

def chunks(n, iterable):
    iterable = iter(iterable)
    while True:
        yield tuple(islice(iterable, n)) or iterable.next()

Aktualizacja: Wersja leniwego kawałków:

from itertools import chain, islice

def chunks(n, iterable):
   iterable = iter(iterable)
   while True:
       yield chain([next(iterable)], islice(iterable, n-1))
17
nikipore 9 listopad 2013, 08:21

Byłem ciekawy o wydajności różnych podejść, a tutaj jest:

Testowany na Pythonie 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)

Wyniki:

slice
31.18285083770752

index
0.02184295654296875

batches 1
0.03503894805908203

batches 2
0.22681021690368652

chunks
0.019841909408569336

grouper
0.006506919860839844
16
Alex T 7 styczeń 2018, 08:58

Kod:

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)

Wynik:

[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
14
buhtz says get vaccinated 31 sierpień 2016, 17:30

Możesz także użyć get_chunks Funkcja {X1}} biblioteka jako:

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

Możesz zainstalować {x0}} przez PIP:

sudo pip install utilspie

Zrzeczenie się: Jestem twórcą Utilspie biblioteka .

13
Anonymous 27 styczeń 2017, 23:12

W tym momencie myślę, że potrzebujemy rekurencyjny generator , na wszelki wypadek ...

W Pythonie 2:

def chunks(li, n):
    if li == []:
        return
    yield li[:n]
    for e in chunks(li[n:], n):
        yield e

W Pythonie 3:

def chunks(li, n):
    if li == []:
        return
    yield li[:n]
    yield from chunks(li[n:], n)

Ponadto, w przypadku masywnej inwazji obcych, urządzony generator rekurencyjny może zostać przydatny:

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 3 listopad 2015, 23:42

Kolejna bardziej wyraźna wersja.

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
9
Ranaivo 28 luty 2015, 20:05

Heh, jedna wersja

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]]
8
slav0nic 23 listopad 2008, 12:51
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

Stosowanie:

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

for seq in split_seq(seq, 3):
    print seq
8
Corey Goldberg 24 listopad 2008, 16:56

Bez wywołania Len (), który jest dobry dla dużych list:

def splitter(l, n):
    i = 0
    chunk = l[:n]
    while chunk:
        yield chunk
        i += n
        chunk = l[i:i+n]

I to jest dla iterables:

def isplitter(l, n):
    l = iter(l)
    chunk = list(islice(l, n))
    while chunk:
        yield chunk
        chunk = list(islice(l, n))

Funkcjonalny smak powyższego:

def isplitter2(l, n):
    return takewhile(bool,
                     (tuple(islice(start, n))
                            for start in repeat(iter(l))))

LUB:

def chunks_gen_sentinel(n, seq):
    continuous_slices = imap(islice, repeat(iter(seq)), repeat(0), repeat(n))
    return iter(imap(tuple, continuous_slices).next,())

LUB:

def chunks_gen_filter(n, seq):
    continuous_slices = imap(islice, repeat(iter(seq)), repeat(0), repeat(n))
    return takewhile(bool,imap(tuple, continuous_slices))
8
parity3 16 maj 2016, 06:29

Ponieważ wszyscy tutaj mówią o iteratorach. boltons ma doskonałą metodę, zwaną iterutils.chunked_iter.

from boltons import iterutils

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

Wynik:

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

Ale jeśli nie chcesz być miłosierdziem na pamięci, możesz użyć w starej drogi i przechowywać pełny list w pierwszej kolejności z iterutils.chunked.

7
vishes_shell 3 listopad 2016, 19:10
def chunks(iterable,n):
    """assumes n is an integer>0
    """
    iterable=iter(iterable)
    while True:
        result=[]
        for i in range(n):
            try:
                a=next(iterable)
            except StopIteration:
                break
            else:
                result.append(a)
        if result:
            yield result
        else:
            break

g1=(i*i for i in range(10))
g2=chunks(g1,3)
print g2
'<generator object chunks at 0x0337B9B8>'
print list(g2)
'[[0, 1, 4], [9, 16, 25], [36, 49, 64], [81]]'
6
robert king 13 luty 2012, 04:50

Rozważ użycie matplotlib.cBook kawałki

Na przykład:

import matplotlib.cbook as cbook
segments = cbook.pieces(np.arange(20), 3)
for s in segments:
     print s
6
schwartrer 8 marzec 2012, 18:27
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 )]
6
AdvilUser 15 lipiec 2015, 23:27

Oto lista dodatkowych podejść:

podane

import itertools as it
import collections as ct

import more_itertools as mit


iterable = range(11)
n = 3

Kod

standardowa biblioteka

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

Referencje

+ Biblioteka osób trzecich, która implementuje Przepisy iTOtools i więcej. > pip install more_itertools

11
pylang 26 sierpień 2018, 01:40