2012-04-12 16 views
12

Normalmente, quiere ir al revés, like here. Me preguntaba cómo se puede convertir una lista plana a una lista de lista, quasy gama remodelación en Pythonconvertir una lista plana en la lista de la lista en python

En numpy que podría hacer algo como:

>>> a=numpy.aranage(9) 
>>> a.reshape(3,3) 
>>> a 
array([[0, 1, 2], 
    [3, 4, 5], 
    [6, 7, 8]]) 

me preguntaba cómo se hace lo contrario, y mi solución habitual es algo así como:

>>> Mylist 
['a', 'b', 'c', 'd', 'e', 'f'] 
>>> newList = [] 
for i in range(0,len(Mylist),2): 
...  newList.append(Mylist[i], Mylist[i+1]) 
>>> newList 
[['a', 'b'], ['c', 'd'], ['e', 'f']] 

¿Hay alguna forma más "pitónica" de hacerlo?

+0

es mejor no usar 'list' como nombre de variable ya que está la función incorporada' list() ' – jamylak

+0

yeap tienes razón, solo estaba editando el código rápidamente, mi código original no se ve así. – Oz123

Respuesta

27
>>> l = ['a', 'b', 'c', 'd', 'e', 'f'] 
>>> zip(*[iter(l)]*2) 
[('a', 'b'), ('c', 'd'), ('e', 'f')] 

Como ha sido señalado por @Lattyware, esto sólo funciona si hay suficientes elementos de cada argumento de la función zip cada vez que devuelve una tupla. Si uno de los parámetros tiene menos elementos que los demás, los elementos se cortan, por ejemplo.

>>> l = ['a', 'b', 'c', 'd', 'e', 'f','g'] 
>>> zip(*[iter(l)]*2) 
[('a', 'b'), ('c', 'd'), ('e', 'f')] 

Si este es el caso, entonces lo mejor es utilizar la solución por @Sven Marnach

How does zip(*[iter(s)]*n) work

+3

Esta solución solo funciona si hay suficientes elementos para llenarla, de lo contrario los artículos se cortan. –

+0

Creando un generador y luego duplicando una referencia al mismo; inteligente. –

+1

@NickT bien técnicamente es un iterador, no un generador y no me puedo atribuir el mérito de la astucia :) – jamylak

11

Esto se hace generalmente usando la receta del mero itertools documentation:

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

Ejemplo:

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] 
>>> list(grouper(2, my_list)) 
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', None)] 
0

Si se prefiere una lista de listas, en lugar de una lista de tuplas de una lista plana, entonces se podría hacer esto:

a = range(20) # sample starting list 
    b = [] # new list 
    c = [] # alternate new list 
    # ny is length of new list. nx length of each list within it 
    nx = 5; ny = 4 
    bb = 0; ee = bb + nx # option one: sliding indeces for slices. 
    for ii in range(ny-1): 
     bb += nx 
     ee += nx 
     b.append(a[bb:ee]) 
     c.append(a[slice(ii*nx,nx*(ii+1))]) # option two, use slice() 

(He jugado un poco con la reducción de la totalidad de bucle en una línea con listas de comprensión, pero no han tenido éxito. la forma en que lo he usado, slice() casi puede llevarte allí.) Una posible ventaja de estos enfoques sobre los otros mencionados es que si tu lista plana original no es un múltiplo par de las dimensiones de tu nuevo, deseado lista de listas, no perderá ningún dato. La advertencia es que la última lista será más corta que todas las demás, ya que contendrá los "restos". Sin embargo, ninguno de estos métodos me parece muy pitónico.

+0

No entiendo por qué estás usando 'slice()' en el segundo enfoque, en lugar de la sintaxis del segmento. Hacer un cálculo no significa que no puedas usar 'a [ii * nx: nx * (ii + 1)]' o lo que sea. – Blckknght

5

Otra forma de crear una lista de listas se puede simplificar como se muestra a continuación:

>>>MyList = ['a','b','c','d','e','f'] 
# Calculate desired row/col 
>>>row = 3 
>>>col = 2 
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)] 
>>>NewList 
[['a', 'b', 'c'], ['d', 'e', 'f']] 

Esto puede método puede extenderse para producir cualquier tamaño de fila y columna. Si selecciona fila y columna valores tales que row*col >len(MyList), la sublista (fila) que contiene el último valor de MyList terminará allí, y NewList simplemente se llena con el número apropiado de listas vacías para satisfacer las especificaciones de fila/col

>>>MyList = ['a','b','c','d','e','f','g','h'] 
>>>row = 3 
>>>col = 3 
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)] 
>>>NewList 
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g','h']] 

>>>row = 4 
>>>col = 4 
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)] 
[['a', 'b', 'c', 'd'], ['e', 'f', 'g','h'], [], []] 
+1

Supongo que debería ser la respuesta aceptada ya que la pregunta era pedir una lista de listas y no una lista de tuplas. O la respuesta de Robert en el comentario anterior. –

Cuestiones relacionadas