2009-08-02 18 views
8

Estoy buscando una función (o mecanismo) incorporada de python para segmentar una lista en las longitudes de segmento requeridas (sin mutar la lista de entrada). Aquí está el código que ya tengo:Segmente una lista en Python

>>> def split_list(list, seg_length): 
...  inlist = list[:] 
...  outlist = [] 
...  
...  while inlist: 
...   outlist.append(inlist[0:seg_length]) 
...   inlist[0:seg_length] = [] 
...  
...  return outlist 
... 
>>> alist = range(10) 
>>> split_list(alist, 3) 
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] 
+0

relacionados http://stackoverflow.com/questions/1915170/split-a-generator -iterable-every-n-items-in-pyt hon-splitevery – jfs

Respuesta

17

Puede utilizar la lista de comprensión:

>>> seg_length = 3 
>>> a = range(10) 
>>> [a[x:x+seg_length] for x in range(0,len(a),seg_length)] 
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] 
+4

También puedes hacer de esto un generador, es decir (a [x: x + seg_length] para x en rango (0, len (a), seg_length)) que será más eficiente para secuencias grandes. – mhawke

+0

Este código de una línea es muy conciso y útil. –

2

no la misma salida, sigo pensando que el grouper function es útil:

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

para python2 .4 y 2.5 que no tiene izip_longest:

from itertools import izip, chain, repeat 
def grouper(iterable, n, padvalue=None): 
    return izip(*[chain(iterable, repeat(padvalue, n-1))]*n) 

algún código de demostración y de salida:

alist = range(10) 
print list(grouper(alist, 3)) 

salida: [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, Nada, Nada) ]

4

¿Cómo necesita utilizar la salida? Si sólo necesita iterar sobre ella, es mejor crear un iterable, uno que produce sus grupos: ejemplo

def split_by(sequence, length): 
    iterable = iter(sequence) 
    def yield_length(): 
     for i in xrange(length): 
      yield iterable.next() 
    while True: 
     res = list(yield_length()) 
     if not res: 
      return 
     yield res 

Uso:

>>> alist = range(10) 
>>> list(split_by(alist, 3)) 
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] 

Esto utiliza mucha menos memoria que tratar de construir el lista entera en la memoria a la vez, si sólo se recorre sobre el resultado, ya que sólo se construye un subconjunto a la vez:

>>> for subset in split_by(alist, 3): 
...  print subset 
... 
[0, 1, 2] 
[3, 4, 5] 
[6, 7, 8] 
[9] 
+0

+1. Un enfoque muy sensato. Tendré esto en cuenta si mis datos de entrada crecen en tamaño. – kjfletch

Cuestiones relacionadas