205 votos

¿Cuál es la manera más "pythonic" para iterar sobre una lista en trozos?

Tengo un script en Python que toma como entrada una lista de enteros, que tengo que trabajar con cuatro enteros en un momento. Por desgracia, no tengo el control de la entrada, o tendría que pasa como una lista de cuatro elementos-tuplas. En la actualidad, estoy de iterar sobre él de esta manera:

for i in xrange(0, len(ints), 4):
    # dummy op for example code
    foo += ints[i] * ints[i + 1] + ints[i + 2] * ints[i + 3]

Se parece mucho a "C-pensar", sin embargo, lo que me hace sospechar que hay un más python el modo de lidiar con esta situación. La lista se desecha después de la iteración, por lo que no tiene que ser preservado. Tal vez algo como esto sería mejor?

while ints:
    foo += ints[0] * ints[1] + ints[2] * ints[3]
    ints[0:4] = []

Todavía no acaba de "sentir" a la derecha, sin embargo. :-/

Relacionado con la pregunta: ¿Cómo se puede dividir una lista en tamaño uniforme de trozos en Python?

207voto

nosklo Puntos 75862
def chunker(seq, size):
    return (seq[pos:pos + size] for pos in xrange(0, len(seq), size))

Simple. Fácil. Rápido. Funciona con cualquier secuencia:

text = "I am a very, very helpful text"

for group in chunker(text, 7):
   print repr(group),
# 'I am a ' 'very, v' 'ery hel' 'pful te' 'xt'

print '|'.join(chunker(text, 10))
# I am a ver|y, very he|lpful text

animals = ['cat', 'dog', 'rabbit', 'duck', 'bird', 'cow', 'gnu', 'fish']

for group in chunker(animals, 3):
    print group
# ['cat', 'dog', 'rabbit']
# ['duck', 'bird', 'cow']
# ['gnu', 'fish']

148voto

Craz Puntos 3664

Modificación de la sección de recetas de documentos itertools de Python:

def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return izip_longest(*args, fillvalue=fillvalue)

Ejemplo
En pesudocode para mantener el ejemplo escueto.

grouper('ABCDEFG', 3, 'x') --> 'ABC' 'DEF' 'Gxx'

Note: izip_longest es nuevo para Python 2.6

37voto

S.Lott Puntos 207588

Soy un fan de

chunkSize= 4
for i in xrange(0, len(ints), chunkSize):
    chunk = ints[i:i+chunkSize]
    # process chunk of size <= chunkSize

14voto

Markus Jarderot Puntos 33893
import itertools
def chunks(iterable,size):
    it = iter(iterable)
    chunk = tuple(itertools.islice(it,size))
    while chunk:
        yield chunk
        chunk = tuple(itertools.islice(it,size))

# though this will throw ValueError if the length of ints
# isn't a multiple of four:
for x1,x2,x3,x4 in chunks(ints,4):
    foo += x1 + x2 + x3 + x4

for chunk in chunks(ints,4):
    foo += sum(chunk)

Otra manera:

import itertools
def chunks2(iterable,size,filler=None):
    it = itertools.chain(iterable,itertools.repeat(filler,size-1))
    chunk = tuple(itertools.islice(it,size))
    while len(chunk) == size:
        yield chunk
        chunk = tuple(itertools.islice(it,size))

# x2, x3 and x4 could get the value 0 if the length is not
# a multiple of 4.
for x1,x2,x3,x4 in chunks2(ints,4,0):
    foo += x1 + x2 + x3 + x4

9voto

Pedro Henriques Puntos 835
from itertools import izip_longest

def chunker(iterable, chunksize, filler):
    return izip_longest(*[iter(iterable)]*chunksize, fillvalue=filler)

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X