parts into python algorithm generator chunking

python - into - cómo dividir un iterable en trozos de tamaño constante



split list python (4)

Como otros han señalado, el código que has dado hace exactamente lo que quieres. Para otro enfoque utilizando itertools.islice , podría ver un example de la siguiente receta:

from itertools import islice, chain def batch(iterable, size): sourceiter = iter(iterable) while True: batchiter = islice(sourceiter, size) yield chain([batchiter.next()], batchiter)

Posible duplicado:
¿Cómo se divide una lista en trozos de tamaño uniforme en Python?

Me sorprende que no haya podido encontrar una función de "lote" que tomaría como entrada un iterable y devolvería un iterable de iterables.

Por ejemplo:

for i in batch(range(0,10), 1): print i [0] [1] ... [9]

o:

for i in batch(range(0,10), 3): print i [0,1,2] [3,4,5] [6,7,8] [9]

Ahora, escribí lo que pensé que era un generador bastante simple:

def batch(iterable, n = 1): current_batch = [] for item in iterable: current_batch.append(item) if len(current_batch) == n: yield current_batch current_batch = [] if current_batch: yield current_batch

Pero lo anterior no me da lo que hubiera esperado:

for x in batch(range(0,10),3): print x [0] [0, 1] [0, 1, 2] [3] [3, 4] [3, 4, 5] [6] [6, 7] [6, 7, 8] [9]

Por lo tanto, me he perdido algo y esto probablemente muestra mi completa falta de comprensión de los generadores de pitón. ¿Alguien quisiera dirigirme en la dirección correcta?

[Edición: al final me di cuenta de que el comportamiento anterior solo ocurre cuando ejecuto esto en ipython en lugar de python en sí]


Esto es probablemente más eficiente (más rápido)

def batch(iterable, n=1): l = len(iterable) for ndx in range(0, l, n): yield iterable[ndx:min(ndx + n, l)] for x in batch(range(0, 10), 3): print x

Se evita construir nuevas listas.


FWIW, las recetas en el módulo de itertools proporcionan este ejemplo:

def grouper(n, iterable, fillvalue=None): "grouper(3, ''ABCDEFG'', ''x'') --> ABC DEF Gxx" args = [iter(iterable)] * n return izip_longest(fillvalue=fillvalue, *args)

Funciona así:

>>> list(grouper(3, range(10))) [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]


Raro, parece funcionar bien para mí en Python 2.x

>>> def batch(iterable, n = 1): ... current_batch = [] ... for item in iterable: ... current_batch.append(item) ... if len(current_batch) == n: ... yield current_batch ... current_batch = [] ... if current_batch: ... yield current_batch ... >>> for x in batch(range(0, 10), 3): ... print x ... [0, 1, 2] [3, 4, 5] [6, 7, 8] [9]