Respuestas:
Qué tal si
map(list, zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Para python 3.x los usuarios pueden usar
list(map(list, zip(*l)))
Explicación:
Hay dos cosas que necesitamos saber para entender lo que está sucediendo:
zip(*iterables)
Esto significa que zip
espera un número arbitrario de argumentos, cada uno de los cuales debe ser iterable. Por ej zip([1, 2], [3, 4], [5, 6])
.args
, f(*args)
llamará de f
tal manera que cada elemento en args
sea un argumento posicional separado de f
.Volviendo a la entrada de la pregunta l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
, zip(*l)
sería equivalente a zip([1, 2, 3], [4, 5, 6], [7, 8, 9])
. El resto es solo asegurarse de que el resultado sea una lista de listas en lugar de una lista de tuplas.
list(zip(*l))
funciona correctamente en Python 3.
zip(*l)
en Python 2), pero obtienes una lista de tuplas, no una lista de listas. Por supuesto, list(list(it))
siempre es lo mismo que list(it)
.
Una forma de hacerlo es con la transposición NumPy. Para una lista, un:
>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
U otro sin cremallera:
>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
map
podía hacer eso. Sin embargo, aquí hay un ligero refinamiento que no requiere 2 llamadas:map(lambda *a: list(a), *l)
map(None, ...)
no parece funcionar para Py3. El generador se crea, pero next()
genera un error de inmediato: TypeError: 'NoneType' object is not callable
.
Equivalente a la solución de Jena:
>>> l=[[1,2,3],[4,5,6],[7,8,9]]
>>> [list(i) for i in zip(*l)]
... [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
map()
, esta solución es la que tiene más espíritu Python ...
solo por diversión, rectángulos válidos y suponiendo que m [0] existe
>>> m = [[1,2,3],[4,5,6],[7,8,9]]
>>> [[row[i] for row in m] for i in range(len(m[0]))]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
[[j[i] for j in l] for i in range(len(l[0]))]
. Por supuesto, debe asegurarse de que la lista l
no esté vacía.
Los métodos 1 y 2 funcionan en Python 2 o 3, y funcionan en irregular, rectangular listas 2D. Eso significa que las listas internas no necesitan tener las mismas longitudes entre sí (desiguales) o que las listas externas (rectangulares). Los otros métodos, bueno, son complicados.
import itertools
import six
list_list = [[1,2,3], [4,5,6, 6.1, 6.2, 6.3], [7,8,9]]
map()
,zip_longest()
>>> list(map(list, six.moves.zip_longest(*list_list, fillvalue='-')))
[[1, 4, 7], [2, 5, 8], [3, 6, 9], ['-', 6.1, '-'], ['-', 6.2, '-'], ['-', 6.3, '-']]
six.moves.zip_longest()
se convierte
itertools.izip_longest()
en Python 2itertools.zip_longest()
en Python 3El valor de relleno predeterminado es None
. Gracias a la respuesta de @ jena , ¿dónde map()
está cambiando las tuplas internas a listas? Aquí está convirtiendo iteradores en listas. Gracias a los comentarios de @ Oregano y @ badp .
En Python 3, pase el resultado list()
para obtener la misma lista 2D que el método 2.
zip_longest()
>>> [list(row) for row in six.moves.zip_longest(*list_list, fillvalue='-')]
[[1, 4, 7], [2, 5, 8], [3, 6, 9], ['-', 6.1, '-'], ['-', 6.2, '-'], ['-', 6.3, '-']]
La alternativa @ inspectorG4dget .
map()
de map()
- roto en Python 3.6>>> map(list, map(None, *list_list))
[[1, 4, 7], [2, 5, 8], [3, 6, 9], [None, 6.1, None], [None, 6.2, None], [None, 6.3, None]]
Esta segunda alternativa extraordinariamente compacta de @SiggyF funciona con listas 2D irregulares, a diferencia de su primer código que usa numpy para transponer y pasar por listas irregulares. Pero Ninguno tiene que ser el valor de relleno. (No, el Ninguno pasado al mapa interno () no es el valor de relleno. Significa que no hay ninguna función para procesar cada columna. Las columnas simplemente se pasan al mapa externo () que las convierte de tuplas a listas.
En algún lugar de Python 3, map()
dejé de soportar todo este abuso: el primer parámetro no puede ser None, y los iteradores irregulares se truncan al más corto. Los otros métodos aún funcionan porque esto solo se aplica al mapa interno ().
map()
de map()
revisitado>>> list(map(list, map(lambda *args: args, *list_list)))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]] // Python 2.7
[[1, 4, 7], [2, 5, 8], [3, 6, 9], [None, 6.1, None], [None, 6.2, None], [None, 6.3, None]] // 3.6+
Por desgracia, las filas irregulares NO se convierten en columnas irregulares en Python 3, solo se truncan. Boo hoo progreso.
solution1 = map(list, zip(*l))
solution2 = [list(i) for i in zip(*l)]
solution3 = []
for i in zip(*l):
solution3.append((list(i)))
print(*solution1)
print(*solution2)
print(*solution3)
# [1, 4, 7], [2, 5, 8], [3, 6, 9]
Quizás no sea la solución más elegante, pero aquí hay una solución que usa bucles while anidados:
def transpose(lst):
newlist = []
i = 0
while i < len(lst):
j = 0
colvec = []
while j < len(lst):
colvec.append(lst[j][i])
j = j + 1
newlist.append(colvec)
i = i + 1
return newlist
import numpy as np
r = list(map(list, np.transpose(l)))
more_itertools.unzip()
es fácil de leer y también funciona con generadores.
import more_itertools
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
r = more_itertools.unzip(l) # a tuple of generators.
r = list(map(list, r)) # a list of lists
o equivalente
import more_itertools
l = more_itertools.chunked(range(1,10), 3)
r = more_itertools.unzip(l) # a tuple of generators.
r = list(map(list, r)) # a list of lists
Aquí hay una solución para transponer una lista de listas que no es necesariamente cuadrada:
maxCol = len(l[0])
for row in l:
rowLength = len(row)
if rowLength > maxCol:
maxCol = rowLength
lTrans = []
for colIndex in range(maxCol):
lTrans.append([])
for row in l:
if colIndex < len(row):
lTrans[colIndex].append(row[colIndex])
#Import functions from library
from numpy import size, array
#Transpose a 2D list
def transpose_list_2d(list_in_mat):
list_out_mat = []
array_in_mat = array(list_in_mat)
array_out_mat = array_in_mat.T
nb_lines = size(array_out_mat, 0)
for i_line_out in range(0, nb_lines):
array_out_line = array_out_mat[i_line_out]
list_out_line = list(array_out_line)
list_out_mat.append(list_out_line)
return list_out_mat
l
no está dimensionado de manera uniforme (por ejemplo, algunas filas son más cortas que otros),zip
será no compensar por ello y en lugar de cortar distancia filas de la salida. Entoncesl=[[1,2],[3,4],[5]]
te da[[1,3,5]]
.