2011-11-10 180 views
53

假設我有一個元組列表,並且我想要轉換爲多個列表。將元組列表轉換爲Python中的多個列表

例如,元組的列表是

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

有沒有在Python任何內置函數,將其轉換爲:

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

這可以是一個簡單的程序。但我只是對Python中這種內置函數的存在感到好奇。

回答

82

內置功能zip()幾乎會做你想要什麼:

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

唯一的區別是,你得到的元組而不是列表。與*運算結合

拉鍊()可以用來解壓縮列表:

具體的例子,你可以使用

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

python docs它們轉換成列表:

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

或者,如果你真的想要名單:

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

用途:

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

添加到克勞迪烏的和克勞迪烏的答案,因爲地圖需要從itertools在Python 3進口的,你也可以使用一個列表理解,如:

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

儘管*zip更Pythonic,下面的代碼有更好的性能:

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

另外,當原始列表zs爲空時,*zip會引發,但此代碼可以正確處理。

我只是跑一個快速實驗,這裏是結果:

Using *zip:  1.54701614s 
Using append: 0.52687597s 

運行它多次,append是3倍 - 比zip快4倍!測試腳本是在這裏:

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

我的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. 
0

franklsf95則用在了他的回答表現和選擇採用list.append(),但他們不是最優的。

添加列表內涵,我結束了以下內容:

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

這給了結果:

zip:   122.11585397789766 
append:   356.44876132614047 
list comp:  144.637765085659 

所以,如果你是演出結束後,你應該使用zip()雖然列表內涵是不太落後。相比之下,append的性能其實很差。