146 votes

Comment convertir une liste de tuples en plusieurs listes?

Supposons que j'ai une liste de tuples et que je veuille la convertir en plusieurs listes.

Par exemple, la liste de tuples est

[(1,2),(3,4),(5,6),]

Y a-t-il une fonction intégrée en Python qui la convertisse en :

[1,3,5],[2,4,6]

Cela peut être un programme simple. Mais je suis juste curieux de savoir si une telle fonction intégrée existe en Python.

212voto

Sven Marnach Points 133943

La fonction intégrée zip() fera presque ce que vous voulez :

>>> list(zip(*[(1, 2), (3, 4), (5, 6)]))
[(1, 3, 5), (2, 4, 6)]

Cela vous donnera une liste de tuples. Si vous voulez aller plus loin et arriver à une liste de listes :

>>> list(map(list, zip(*[(1, 2), (3, 4), (5, 6)])))
[[1, 3, 5], [2, 4, 6]]

0 votes

En Python, vous devez convertir l'itérateur résultant en une liste pour voir le contenu: list(zip(*[(1, 2), (3, 4), (5, 6)])).

1 votes

@MERose Cette réponse a été écrite pour Python 2. À l'époque, zip() et map() retournaient des listes, pas des itérateurs paresseux, comme c'est le cas en Python 3. Je mettrai à jour la réponse.

0 votes

Je sais, je sais. Mon commentaire était destiné à éviter la confusion chez les auditeurs d'aujourd'hui. Aussi, j'ai oublié d'écrire "Python 3".

51voto

Claudiu Points 58398

De docs python :

zip() en conjonction avec l'opérateur * peut être utilisé pour dézipper une liste :

Exemple spécifique :

>>> zip((1,3,5),(2,4,6))
[(1, 2), (3, 4), (5, 6)]
>>> zip(*[(1, 2), (3, 4), (5, 6)])
[(1, 3, 5), (2, 4, 6)]

Ou, si vous voulez vraiment des listes :

>>> map(list, zip(*[(1, 2), (3, 4), (5, 6)]))
[[1, 3, 5], [2, 4, 6]]

9voto

Artsiom Rudzenka Points 9771
>>> a = [(1,2),(3,4),(5,6),]    
>>> zip(*a)
[(1, 3, 5), (2, 4, 6)]

6voto

Baldrickk Points 2699

Franklsf95 opte pour la performance dans sa réponse et opte pour list.append(), mais ce n'est pas optimal.

En ajoutant des compréhensions de liste, j'ai fini par obtenir ce qui suit:

def t1(zs):
    xs, ys = zip(*zs)
    return xs, ys

def t2(zs):
    xs, ys = [], []
    for x, y in zs:
        xs.append(x)
        ys.append(y)
    return xs, ys

def t3(zs):
    xs, ys = [x for x, y in zs], [y for x, y in zs]
    return xs, ys

if __name__ == '__main__':
    from timeit import timeit
    setup_string='''\
N = 2000000
xs = list(range(1, N))
ys = list(range(N+1, N*2))
zs = list(zip(xs, ys))
from __main__ import t1, t2, t3
'''
    print(f'zip:\t\t{timeit('t1(zs)', setup=setup_string, number=1000)}')
    print(f'append:\t\t{timeit('t2(zs)', setup=setup_string, number=1000)}')
    print(f'list comp:\t{timeit('t3(zs)', setup=setup_string, number=1000)}')

Cela a donné le résultat:

zip:            122.11585397789766
append:         356.44876132614047
list comp:      144.637765085659

Donc, si vous recherchez la performance, vous devriez probablement utiliser zip() bien que les compréhensions de liste ne soient pas trop loin. La performance de append est en fait assez mauvaise en comparaison.

5voto

franklsf95 Points 909

Malgré le fait que *zip soit plus Pythonique, le code suivant a de bien meilleures performances :

xs, ys = [], []
for x, y in zs:
    xs.append(x)
    ys.append(y)

Aussi, lorsque la liste originale zs est vide, *zip va lever une erreur, mais ce code peut gérer cela correctement.

Je viens de faire une rapide expérience, et voici le résultat :

Utilisation de *zip :     1.54701614s
Utilisation de append :   0.52687597s

En le lançant plusieurs fois, append est 3 à 4 fois plus rapide que zip ! Le script de test est le suivant :

#!/usr/bin/env python3
import time

N = 2000000
xs = list(range(1, N))
ys = list(range(N+1, N*2))
zs = list(zip(xs, ys))

t1 = time.time()

xs_, ys_ = zip(*zs)
print(len(xs_), len(ys_))

t2 = time.time()

xs_, ys_ = [], []
for x, y in zs:
    xs_.append(x)
    ys_.append(y)
print(len(xs_), len(ys_))

t3 = time.time()

print('Utilisation de *zip :\t{:.8f}s'.format(t2 - t1))
print('Utilisation de append :\t{:.8f}s'.format(t3 - t2))

Ma version de Python :

Python 3.6.3 (default, Oct 24 2017, 12:18:40)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] sur darwin
Tapez "help", "copyright", "credits" ou "license" pour plus d'informations.

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