2010-02-09 24 views
22

¿Cuál es la forma más simple y razonablemente eficiente de dividir una lista en una lista de secciones de sub-listas segmentadas para sublistas de longitud arbitraria?Cortar una lista en una lista de sub-listas

Por ejemplo, si nuestra lista de fuentes es:

input = [1, 2, 3, 4, 5, 6, 7, 8, 9, ... ] 

Y nuestro longitud de la lista de sub es 3, entonces buscamos:

output = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ... ] 

Del mismo modo, si nuestra longitud de la lista de sub es 4, entonces buscamos:

output = [ [1, 2, 3, 4], [5, 6, 7, 8], ... ] 
+2

@James: su adición no tiene absolutamente ninguna relevancia. – SilentGhost

+1

Puede que esté interesado en la discusión de esta pregunta (http://stackoverflow.com/questions/2095637) – telliott99

+0

Puede usar la función numeración array_split, por ejemplo, 'np.array_split (np.array (data), 20)' para dividir en 20 pedazos de tamaño casi igual. Para asegurarse de que los trozos sean exactamente iguales, use 'np.split'. – AlexG

Respuesta

64
[input[i:i+n] for i in range(0, len(input), n)]  # use xrange in py2k 

donde n es la longitud de un fragmento.

Dado que no se define qué podría pasar con el elemento final de la nueva lista cuando el número de elementos en input no es divisible por n, asumí que no tiene importancia: con esto obtendrá el último elemento igual a 2 si n es igual a 7, por ejemplo.

14

La documentación del módulo itertools contiene la siguiente recipe:

import itertools 

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

Esta función devuelve un iterador de tuplas de la longitud deseada:

>>> list(grouper(2, [1,2,3,4,5,6,7])) 
[(1, 2), (3, 4), (5, 6), (7, None)] 
+0

mientras esto funciona con cualquier iterable, no parece ser tan eficiente (al menos en mis pruebas) como mi código cuando se aplica a la tarea dada. – SilentGhost

+3

@SilentGhost, optimización prematura? –

+1

@Mike: ¿Perdón? – SilentGhost

0

me gusta la solución de SilentGhost.

Mi solución utiliza la programación funcional en Python:

group = lambda t, n: zip(*[t[i::n] for i in range(n)]) 
group([1, 2, 3, 4], 2) 

da:

[(1, 2), (3, 4)] 

Esto supone que el tamaño de la lista de entrada es divisible por el tamaño del grupo. Si no, los elementos no apareados no serán incluidos.

+0

su segundo ejemplo está limitado a python-2.x. en py3k 'map' no puede tomar' None' como primer argumento. – SilentGhost

+0

@SilentGhost: tienes razón, lo eliminaré sin embargo. – MKTech

7

Una variante muy Pythonic (Python 3):

list(zip(*(iter([1,2,3,4,5,6,7,8,9]),)*3)) 

Se crea un iterador de lista y se convirtió en una tupla con 3x el mismo repetidor, a continuación, desempaquetado para comprimir y fundido a la lista de nuevo. Se extrae un valor de cada iterador por zip, pero como solo hay un único objeto iterador, el contador interno se incrementa globalmente para los tres.

+2

Esta solución es brillante, pero si tuviera que considerar el zen de pitón, diría que no es muy "pitónico": P – AkiRoss

+1

Es cierto que es una solución no pitthonic pythonic ;-) – CoDEmanX

+0

NO funciona si el mod de len de la lista no es 0! –

Cuestiones relacionadas