Wie konvertiere ich eine Liste von Tupeln in mehrere Listen?

105

Angenommen, ich habe eine Liste mit Tupeln und möchte in mehrere Listen konvertieren.

Zum Beispiel ist die Liste der Tupel

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

Gibt es eine integrierte Funktion in Python, die es konvertiert in:

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

Dies kann ein einfaches Programm sein. Aber ich bin nur neugierig auf die Existenz einer solchen integrierten Funktion in Python.

xiaohan2012
quelle

Antworten:

159

Die eingebaute Funktion macht zip()fast das, was Sie wollen:

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

Der einzige Unterschied besteht darin, dass Sie Tupel anstelle von Listen erhalten. Sie können sie mit in Listen konvertieren

map(list, zip(*[(1, 2), (3, 4), (5, 6)]))
Sven Marnach
quelle
40

Aus den Python-Dokumenten :

Mit zip () kann in Verbindung mit dem Operator * eine Liste entpackt werden:

Spezifisches Beispiel:

>>> 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)]

Oder wenn Sie wirklich Listen wollen:

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

Verwenden:

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

franklsf95 strebt in seiner Antwort nach Leistung und entscheidet sich für list.append(), aber sie sind nicht optimal.

Beim Hinzufügen von Listenverständnissen kam ich zu folgendem Ergebnis:

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)}')

Dies ergab das Ergebnis:

zip:            122.11585397789766
append:         356.44876132614047
list comp:      144.637765085659

Wenn Sie also nach der Aufführung sind, sollten Sie wahrscheinlich verwenden, zip()obwohl das Listenverständnis nicht zu weit zurückliegt. Die Leistung von appendist im Vergleich eigentlich ziemlich schlecht.

Baldrickk
quelle
1

Obwohl *zipder folgende Code pythonischer ist, bietet er eine viel bessere Leistung:

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

Auch wenn die ursprüngliche Liste zsleer ist, *zipwird ausgelöst, aber dieser Code kann richtig verarbeiten.

Ich habe gerade ein kurzes Experiment durchgeführt und hier ist das Ergebnis:

Using *zip:     1.54701614s
Using append:   0.52687597s

Mehrfaches Ausführen appendist 3x - 4x schneller als zip! Das Testskript ist hier:

#!/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))

Meine Python-Version:

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.
franklsf95
quelle
1

Zusätzlich zu Claudius Antwort können Sie Folgendes verwenden:

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

Bearbeitet nach @Peyman mohseni kiasari

Eric Lin
quelle
1
Nein! es wird dir geben (1, 3, 5)und (2, 4, 6)keine Listen. Sie sollten verwendenmap(list, zip(*[(1, 2), (3, 4), (5, 6)]))
Peyman
0

Wenn Sie die Antwort von Claudiu und Claudiu ergänzen und die Karte aus den itertools in Python 3 importiert werden muss, verwenden Sie auch ein Listenverständnis wie:

[[*x] for x in zip(*[(1,2),(3,4),(5,6)])]
>>> [[1, 3, 5], [2, 4, 6]]
Quickbeam2k1
quelle