Respostas:
E se
map(list, zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Para python 3.x, os usuários podem usar
list(map(list, zip(*l)))
Explicação:
Há duas coisas que precisamos saber para entender o que está acontecendo:
zip(*iterables)
isso significa que zip
espera um número arbitrário de argumentos, cada um dos quais deve ser iterável. Por exemplo zip([1, 2], [3, 4], [5, 6])
.args
, f(*args)
chamará f
tal que cada elemento em args
seja um argumento posicional separado de f
.Voltando à entrada da pergunta l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
, zip(*l)
seria equivalente a zip([1, 2, 3], [4, 5, 6], [7, 8, 9])
. O resto é apenas garantir que o resultado seja uma lista de listas em vez de uma lista de tuplas.
list(zip(*l))
funciona corretamente em Python 3.
zip(*l)
no Python 2), mas você obtém uma lista de tuplas, não uma lista de listas. Claro, list(list(it))
é sempre a mesma coisa que list(it)
.
Uma maneira de fazer isso é com a transposição do NumPy. Para uma lista, a:
>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Ou outro sem zip:
>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
map
poderia fazer isso. Aqui está um leve refinamento que não requer duas chamadas, no entanto:map(lambda *a: list(a), *l)
map(None, ...)
parece não funcionar para o Py3. O gerador é criada, mas next()
gera um erro imediatamente: TypeError: 'NoneType' object is not callable
.
Equivalentemente à solução 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 solução é aquela que é a mais no espírito Python ...
apenas por diversão, retângulos válidos e assumindo 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]))]
. Obviamente, você precisa ter certeza de que a lista l
não está vazia.
Os métodos 1 e 2 funcionam em Python 2 ou 3 e funcionam em retângulos irregulares listas 2D . Isso significa que as listas internas não precisam ter os mesmos comprimentos entre si (irregulares) ou como as listas externas (retangulares). Os outros métodos, bem, são 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()
torna-se
itertools.izip_longest()
em Python 2itertools.zip_longest()
em Python 3O valor de preenchimento padrão é None
. Graças à resposta de @ jena , onde map()
está alterando as tuplas internas para listas. Aqui está transformando iteradores em listas. Graças a @ e do Oregano de @ badp comentários .
No Python 3, passe o resultado list()
para obter a mesma lista 2D do 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, '-']]
A alternativa @ inspectorG4dget .
map()
of map()
- quebrado em 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]]
Essa segunda alternativa extraordinariamente compacta do @SiggyF funciona com listas 2D irregulares, ao contrário de seu primeiro código, que usa numpy para transpor e passar por listas irregulares. Mas Nenhum deve ser o valor de preenchimento. (Não, o None passado para o mapa interno () não é o valor de preenchimento. Isso significa que não há função para processar cada coluna. As colunas são passadas apenas para o mapa externo () que as converte de tuplas em listas.
Em algum lugar do Python 3, map()
parou de tolerar todo esse abuso: o primeiro parâmetro não pode ser None e os iteradores irregulares são truncados no menor tempo possível. Os outros métodos ainda funcionam porque isso se aplica apenas ao 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+
Infelizmente, as linhas irregulares NÃO se tornam colunas irregulares no Python 3, elas são apenas truncadas. Boo hoo progresso.
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]
Talvez não seja a solução mais elegante, mas aqui está uma solução usando loops while aninhados:
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()
é fácil de ler e também funciona com geradores.
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
ou 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
Aqui está uma solução para transpor uma lista de listas que não é necessariamente quadrada:
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
não é dimensionada de maneira uniforme (por exemplo, algumas linhas são mais curtas do que outros),zip
será não compensá-lo e, em vez corta fora as linhas da saída. Entãol=[[1,2],[3,4],[5]]
te dá[[1,3,5]]
.