web-dev-qa-db-fra.com

Transposer une liste de listes

Prenons:

l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Le résultat que je recherche est

r = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

et pas

r = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

Très appréciée

191
titus

Que diriez-vous

map(list, Zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Pour python _, les utilisateurs 3.x peuvent utiliser

list(map(list, Zip(*l)))
265
jena

Une façon de le faire est d'utiliser 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]]
54
SiggyF

De manière équivalente à la solution 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]]
44
inspectorG4dget

juste pour le fun, 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]]
23
matchew

Les deux premières méthodes fonctionnent dans Python 2 ou 3 et fonctionnent sur des listes 2D rectangulaires "en lambeaux". C'est-à-dire que les listes intérieures n'ont pas besoin d'avoir les mêmes longueurs. Les autres méthodes, c'est compliqué.

la mise en place

import itertools
import six

list_list = [[1,2,3], [4,5,6, 6.1, 6.2, 6.3], [7,8,9]]

méthode 1 - 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

La valeur de remplissage par défaut est None. Merci à @ jena's answer , où map() remplace les n-uplets internes en listes. Ici, il s'agit de transformer des itérateurs en listes. Merci à @ Origan et à @ Badp commentaires .

Dans Python 3, transmettez le résultat via list() pour obtenir la même liste 2D que la méthode 2.


méthode 2 - list comprehension, 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, '-']]

Le alternative à @ inspectorG4dget .


méthode 3 - map() of map() - cassé dans 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]]

Ce format extraordinairement compact @ seconde alternative de SiggyF fonctionne avec des listes 2D irrégulières, contrairement à son premier code qui utilise numpy transpose et passe à travers des listes irrégulières. Mais None doit être la valeur de remplissage. (Non, la valeur None passée à la carte interne () n'est pas la valeur de remplissage. Cela signifie qu'il n'y a pas de fonction permettant de traiter chaque colonne. Elles sont simplement transmises à la carte externe () qui les convertit en listes.

Quelque part dans Python 3, map() a cessé de supporter tout cet abus: le premier paramètre ne peut pas être Aucun et les itérateurs fragmentés sont simplement tronqués au plus court. Les autres méthodes fonctionnent toujours car cela ne s'applique qu'à la carte interne ().


méthode 4 - map() of 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 en lambeaux NE deviennent PAS des colonnes en lambeaux dans Python 3, elles sont simplement tronquées. Boo hoo progrès.

19
Bob Stein

Trois options au choix:

1. Carte avec Zip

solution1 = map(list, Zip(*l))

2. Compréhension de liste

solution2 = [list(i) for i in Zip(*l)]

3. Pour l'ajout de boucle

solution3 = []
for i in Zip(*l):
    solution3.append((list(i)))

Et pour voir les résultats:

print(*solution1)
print(*solution2)
print(*solution3)

# [1, 4, 7], [2, 5, 8], [3, 6, 9]
2
jasonleonhard

Peut-être pas la solution la plus élégante, mais voici une solution utilisant des boucles while imbriquées:

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
1
footballman2399
import numpy as np
r = list(map(list, np.transpose(l)))
0
reza.cse08