161 votes

Matrix Transpose en Python

J'essaie de créer une fonction de transposition de matrice pour python mais je n'arrive pas à le faire fonctionner. Dis que j'ai

 theArray = [['a','b','c'],['d','e','f'],['g','h','i']]
 

et je veux que ma fonction arrive avec

 newArray = [['a','d','g'],['b','e','h'],['c', 'f', 'i']]
 

En d'autres termes, si je devais imprimer ce tableau 2D sous forme de colonnes et de lignes, j'aimerais que les lignes se transforment en colonnes et que les colonnes en lignes.

J'ai fait ça jusqu'ici mais ça ne marche pas

 def matrixTranspose(anArray):
    transposed = [None]*len(anArray[0])
    for t in range(len(anArray)):
        for tt in range(len(anArray[t])):
            transposed[t] = [None]*len(anArray)
            transposed[t][tt] = anArray[tt][t]
    print transposed
 

346voto

J.F. Sebastian Points 102961
>>> theArray = [['a','b','c'],['d','e','f'],['g','h','i']]
>>> zip(*theArray)
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]

68voto

sqwerl Points 249
 >>> theArray = [['a','b','c'],['d','e','f'],['g','h','i']]
>>> [list(i) for i in zip(*theArray)]
[['a', 'd', 'g'], ['b', 'e', 'h'], ['c', 'f', 'i']]
 

le générateur de liste crée un nouveau tableau 2D avec des éléments de liste au lieu de tuples.

42voto

bigjim Points 492

Si vos lignes ne sont pas égales, vous pouvez également utiliser map :

 >>> uneven = [['a','b','c'],['d','e'],['g','h','i']]
>>> map(None,*uneven)
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', None, 'i')]
 

Edit: En Python 3, les fonctionnalités de map modifiées, itertools.zip_longest peuvent être utilisées à la place:
Source: Nouveautés de Python 3.0

 >>> import itertools
>>> uneven = [['a','b','c'],['d','e'],['g','h','i']]
>>> list(itertools.zip_longest(*uneven))
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', None, 'i')]
 

9voto

Ned Batchelder Points 128913

Le problème avec votre code d'origine était que vous aviez initialisé transpose[t] à chaque élément, plutôt qu'une seule fois par ligne:

 def matrixTranspose(anArray):
    transposed = [None]*len(anArray[0])
    for t in range(len(anArray)):
        transposed[t] = [None]*len(anArray)
        for tt in range(len(anArray[t])):
            transposed[t][tt] = anArray[tt][t]
    print transposed
 

Cela fonctionne, bien qu'il existe davantage de méthodes Pythonic pour accomplir les mêmes tâches, notamment l'application zip @ JF.

5voto

Franck Dernoncourt Points 4769

Pour compléter J. F. Sebastian de la réponse, si vous avez une liste de listes de longueurs différentes, découvrez ce grand poste de ActiveState. En bref:

La fonction intégrée zip a fait un travail similaire, mais tronque le résultat à la longueur de la plus courte liste, de sorte que certains éléments de l'original les données peuvent être perdues par la suite.

Pour gérer des listes de listes de longueurs différentes, utilisez:

def transposed(lists):
   if not lists: return []
   return map(lambda *row: list(row), *lists)

def transposed2(lists, defval=0):
   if not lists: return []
   return map(lambda *row: [elem or defval for elem in row], *lists)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X