Comment convertir une liste de tuples en plusieurs listes?


110

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

Par exemple, la liste des tuples est

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

Existe-t-il une fonction intégrée dans Python qui le convertit en:

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

Cela peut être un programme simple. Mais je suis simplement curieux de connaître l'existence d'une telle fonction intégrée en Python.

Réponses:


164

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

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

La seule différence est que vous obtenez des tuples au lieu de listes. Vous pouvez les convertir en listes en utilisant

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

40

À partir de la documentation Python :

zip () en conjonction avec l'opérateur * peut être utilisé pour décompresser 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]]


4

franklsf95 opte pour la performance dans sa réponse et opte pour list.append(), mais elles ne sont pas optimales.

En ajoutant des compréhensions de liste, je me suis retrouvé avec 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 êtes après la performance, vous devriez probablement utiliser zip()bien que les compréhensions de liste ne soient pas trop loin derrière. Les performances de appendsont en fait assez médiocres en comparaison.


1

Bien qu'il *zipsoit plus pythonique, le code suivant a de bien meilleures performances:

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

En outre, lorsque la liste d'origine zsest vide, *zipse lèvera, mais ce code peut gérer correctement.

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

Using *zip:     1.54701614s
Using append:   0.52687597s

L'exécuter plusieurs fois appendest 3x - 4x plus rapide que zip! Le script de test est ici:

#!/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('Using *zip:\t{:.8f}s'.format(t2 - t1))
print('Using append:\t{:.8f}s'.format(t3 - t2))

Ma version 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)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

1

En plus de la réponse de Claudiu, vous pouvez utiliser:

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

Édité selon @Peyman mohseni kiasari


1
Non! il vous donnera (1, 3, 5)et (2, 4, 6)non des listes. vous devriez utilisermap(list, zip(*[(1, 2), (3, 4), (5, 6)]))
Peyman

0

En plus de la réponse de Claudiu et Claudiu et puisque la carte doit être importée d'itertools en python 3, vous utilisez également une compréhension de liste comme:

[[*x] for x in zip(*[(1,2),(3,4),(5,6)])]
>>> [[1, 3, 5], [2, 4, 6]]
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.