Risposte:
Che ne dite di
map(list, zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Per gli utenti di Python 3.x possono usare
list(map(list, zip(*l)))
Spiegazione:
Ci sono due cose che dobbiamo sapere per capire cosa sta succedendo:
zip(*iterables)
questo significa che si zip
aspetta un numero arbitrario di argomenti ciascuno dei quali deve essere iterabile. Es zip([1, 2], [3, 4], [5, 6])
.args
, f(*args)
chiamerà in modo f
tale che ogni elemento in args
sia un argomento posizionale separato di f
.Tornando all'ingresso dalla questione l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
, zip(*l)
sarebbe equivalente a zip([1, 2, 3], [4, 5, 6], [7, 8, 9])
. Il resto è solo assicurarsi che il risultato sia un elenco di elenchi anziché un elenco di tuple.
list(zip(*l))
correttamente in Python 3.
zip(*l)
in Python 2), ma ottieni un elenco di tuple, non un elenco di elenchi. Certo, list(list(it))
è sempre la stessa cosa di list(it)
.
Un modo per farlo è con la trasposizione NumPy. Per un elenco, a:
>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
O un altro senza zip:
>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
map
potesse farlo. Ecco un leggero perfezionamento che non richiede 2 chiamate, però:map(lambda *a: list(a), *l)
map(None, ...)
non sembra funzionare per Py3. Il generatore è stato creato, ma next()
genera immediatamente un errore: TypeError: 'NoneType' object is not callable
.
Equivalente alla soluzione di 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()
, questa soluzione è quella che è la più nello spirito di Python ...
solo per divertimento, rettangoli validi e supponendo che m [0] esista
>>> 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]))]
. Certo, devi essere sicuro che l'elenco l
non sia vuoto.
I metodi 1 e 2 funzionano in Python 2 o 3 e funzionano su elenchi 2D irregolari e rettangolari . Ciò significa che le liste interne non devono avere le stesse lunghezze tra loro (sfilacciate) o delle liste esterne (rettangolari). Gli altri metodi, beh, sono complicati.
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()
diventa
itertools.izip_longest()
in Python 2itertools.zip_longest()
in Python 3Il valore di riempimento predefinito è None
. Grazie alla risposta di @jena , dove map()
sta cambiando le tuple interne in liste. Qui sta trasformando gli iteratori in liste. Grazie ai commenti di @ Oregano e @ badp .
In Python 3, passa il risultato attraverso list()
per ottenere lo stesso elenco 2D del metodo 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, '-']]
L' alternativa @ inspectorG4dget .
map()
of map()
- broken in 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]]
Questa seconda alternativa straordinariamente compatta di @SiggyF funziona con elenchi 2D irregolari, a differenza del suo primo codice che usa numpy per trasporre e passare attraverso elenchi irregolari. Ma None deve essere il valore di riempimento. (No, Nessuno passato alla mappa interna () non è il valore di riempimento. Significa che non esiste alcuna funzione per elaborare ciascuna colonna. Le colonne vengono semplicemente passate alla mappa esterna () che le converte da tuple in elenchi.
Da qualche parte in Python 3, ha map()
smesso di sopportare tutto questo abuso: il primo parametro non può essere Nessuno e gli iteratori irregolari sono solo troncati al più breve. Gli altri metodi funzionano ancora perché questo si applica solo alla mappa interna ().
map()
di map()
rivisitato>>> 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+
Purtroppo le righe irregolari NON diventano colonne irregolari in Python 3, sono solo troncate. Boo hoo progress.
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]
Forse non è la soluzione più elegante, ma ecco una soluzione che utilizza i cicli while annidati:
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()
è facile da leggere e funziona anche con generatori.
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 equivalentemente
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
Ecco una soluzione per trasporre un elenco di elenchi che non è necessariamente quadrato:
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
non è uniformemente dimensioni (ad esempio, alcune righe sono brevi rispetto ad altri),zip
sarà non compensare e invece tagliare via righe dall'output. Quindil=[[1,2],[3,4],[5]]
ti dà[[1,3,5]]
.