2010-09-30 17 views
5

¿Qué es el equivalente a pitones de Ruby's each_slice(count)?
Quiero tomar 2 elementos de la lista para cada iteración.
Me gusta para [1,2,3,4,5,6] Quiero manejar 1,2 en la primera iteración luego 3,4 luego 5,6.
Por supuesto, hay una forma indirecta de usar valores de índice. Pero, ¿hay una función directa o de alguna manera para hacer esto directamente?Python equivalente a cada_slice de Ruby (conteo)

+0

La respuesta de la marca cumple por completo las especificaciones que proporcionó en su pregunta. Sin embargo, es importante tener en cuenta que el comportamiento que especificó se desvía del ruby ​​each_slice: si el último slice es más corto que el resto, se rellenará con fillvalue, mientras que en ruby's each_slice no será más que un array acortado. Si desea esta lista abreviada/comportamiento iterable, entonces la respuesta de Mark no funcionará. – bwv549

Respuesta

9

Hay una recipe para esto en el itertools documentation llamado mero:

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

uso como esto:

>>> l = [1,2,3,4,5,6] 
>>> for a,b in grouper(2, l): 
>>>  print a, b 

1 2 
3 4 
5 6 
+0

Nota: use ** zip_longest ** en lugar de ** izip_longest ** para python 3. – bwv549

2

Igual que Marcos, pero renombrado a 'each_slice' y trabaja para Python 2 y 3 :

try: 
    from itertools import izip_longest # python 2 
except ImportError: 
    from itertools import zip_longest as izip_longest # python 3 

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

Duplica el comportamiento de ruby's each_slice para un pequeño trai ling rebanada:

def each_slice(size, iterable): 
    """ Chunks the iterable into size elements at a time, each yielded as a list. 

    Example: 
     for chunk in each_slice(2, [1,2,3,4,5]): 
      print(chunk) 

     # output: 
     [1, 2] 
     [3, 4] 
     [5] 
    """ 
    current_slice = [] 
    for item in iterable: 
     current_slice.append(item) 
     if len(current_slice) >= size: 
      yield current_slice 
      current_slice = [] 
    if current_slice: 
     yield current_slice 

las respuestas anteriores almohadilla voluntad la última lista (es decir, [5, Ninguno]), que puede no ser lo que se desea en algunos casos.

0

Una mejora en los dos primeros: si el elemento iterable cortado no es exactamente divisible por n, el último se rellenará con n a la longitud n. Si esto está causando que escribe errores, puede hacer un pequeño cambio:

def each_slice(iterable, n, fillvalue=None): 
    args = [iter(iterable)] * n 
    raw = izip_longest(fillvalue=fillvalue, *args) 
    return [filter(None, x) for x in raw] 

Tenga en cuenta que esto eliminará todo Nada es de la gama, por lo que sólo debe utilizarse en casos donde no se producirán errores en el camino.