Réponses:
Que diriez-vous
map(list, zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Pour python 3.x, les utilisateurs peuvent utiliser
list(map(list, zip(*l)))
Explication:
Il y a deux choses que nous devons savoir pour comprendre ce qui se passe:
zip(*iterables)
Cela signifie qu'il zip
attend un nombre arbitraire d'arguments dont chacun doit être itérable. Par exemple zip([1, 2], [3, 4], [5, 6])
.args
, f(*args)
appellera de f
telle sorte que chaque élément dans args
est un argument positionnel distinct de f
.Revenir à l'apport de la question l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
, zip(*l)
serait équivalent à zip([1, 2, 3], [4, 5, 6], [7, 8, 9])
. Le reste s'assure simplement que le résultat est une liste de listes au lieu d'une liste de tuples.
list(zip(*l))
fonctionne correctement en Python 3.
zip(*l)
dans Python 2), mais vous obtenez une liste de tuples, pas une liste de listes. Bien sûr, list(list(it))
c'est toujours la même chose que list(it)
.
Une façon de le faire est avec la transposition NumPy. Pour une liste, un:
>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Ou un autre sans zip:
>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
map
je pouvais faire ça. Voici un léger raffinement qui ne nécessite pas 2 appels, cependant:map(lambda *a: list(a), *l)
map(None, ...)
ne semble pas fonctionner pour Py3. Le générateur est créé , mais next()
déclenche une erreur immédiatement: TypeError: 'NoneType' object is not callable
.
De manière équivalente à la solution d'Iéna:
>>> 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()
, cette solution est celle qui est la plus dans l'esprit Python ...
juste pour le plaisir, des rectangles valides et en supposant 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]))]
. Bien sûr, vous devez vous assurer que la liste l
n'est pas vide.
Les méthodes 1 et 2 fonctionnent en Python 2 ou 3, et elles fonctionnent sur des listes 2D rectangulaires irrégulières . Cela signifie que les listes internes n'ont pas besoin d'avoir les mêmes longueurs les unes par rapport aux autres (irrégulières) ou que les listes externes (rectangulaires). Les autres méthodes, eh bien, c'est compliqué.
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()
devient
itertools.izip_longest()
en Python 2itertools.zip_longest()
en Python 3La valeur de remplissage par défaut est None
. Merci à la réponse de @ jena , où map()
change les tuples internes en listes. Ici, il transforme les itérateurs en listes. Merci aux commentaires de @ Oregano et @ badp .
En Python 3, transmettez le résultat list()
pour obtenir la même liste 2D que la méthode 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' alternative @ inspectorG4dget .
map()
of map()
- broken 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]]
Cette deuxième alternative extraordinairement compacte @SiggyF fonctionne avec des listes 2D déchiquetées, contrairement à son premier code qui utilise numpy pour transposer et passer à travers des listes déchiquetées. Mais aucun ne doit être la valeur de remplissage. (Non, le Aucun transmis à la carte interne () n'est pas la valeur de remplissage. Cela signifie qu'il n'y a pas de fonction pour traiter chaque colonne. Les colonnes sont simplement transmises à la carte externe () qui les convertit des tuples en listes.
Quelque part dans Python 3, a map()
cessé de supporter tous ces abus: le premier paramètre ne peut pas être None, et les itérateurs irréguliers sont simplement tronqués au plus court. Les autres méthodes fonctionnent toujours car cela ne s'applique qu'à la carte intérieure ().
map()
de map()
revisité>>> 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+
Hélas, les lignes irrégulières ne deviennent PAS des colonnes irrégulières en Python 3, elles sont juste tronquées. 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]
Peut-être pas la solution la plus élégante, mais voici une solution utilisant des boucles imbriquées while:
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()
est facile à lire et fonctionne également avec les générateurs.
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 équivalent
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
Voici une solution pour transposer une liste de listes qui n'est pas forcément carrée:
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'est pas de taille égale (par exemple, certaines lignes sont plus courtes que d'autres),zip
il ne le compensera pas et découpera les lignes de la sortie.l=[[1,2],[3,4],[5]]
Vous donne donc[[1,3,5]]
.