2011-11-10 47 views
53

Giả sử tôi có một danh sách các bộ dữ liệu và tôi muốn chuyển đổi thành nhiều danh sách.chuyển danh sách các bộ dữ liệu thành nhiều danh sách trong Python

Ví dụ, danh sách các hàng là

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

Có bất kỳ built-in chức năng bằng Python mà chuyển nó sang:

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

Đây có thể là một chương trình đơn giản. Nhưng tôi chỉ tò mò về sự tồn tại của hàm dựng sẵn như vậy trong Python.

Trả lời

82

Việc xây dựng trong chức năng zip() gần như sẽ làm những gì bạn muốn:

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

Sự khác biệt duy nhất là bạn sẽ có được bộ dữ liệu thay vì danh sách. Bạn có thể chuyển đổi chúng vào danh sách sử dụng

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

Từ python docs:

zip() kết hợp với các nhà điều hành * có thể được sử dụng để giải nén một danh sách:

Ví dụ cụ thể:

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

Hoặc, nếu bạn thực sự muốn danh sách:

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

Sử dụng:

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

Thêm vào của Claudiu và câu trả lời của Claudiu và kể từ khi bản đồ cần phải được nhập khẩu từ itertools trong python 3, bạn cũng sử dụng một danh sách hiểu như:

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

Mặc dù *zip là nhiều Pythonic, mã sau có hiệu suất tốt hơn nhiều:

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

Ngoài ra, khi danh sách gốc zs trống, *zip sẽ tăng, nhưng mã này có thể xử lý đúng cách.

Tôi chỉ cần chạy một thử nghiệm nhanh, và đây là kết quả:

Using *zip:  1.54701614s 
Using append: 0.52687597s 

Chạy nó nhiều lần, append là 3x - 4x nhanh hơn zip! Các kịch bản thử nghiệm là ở đây:

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

My 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. 
0

franklsf95 đi để thực hiện trong câu trả lời của mình và opts cho list.append(), nhưng họ không phải là tối ưu.

Thêm comprehensions danh sách, tôi đã kết thúc như sau:

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

này đã cho kết quả:

zip:   122.11585397789766 
append:   356.44876132614047 
list comp:  144.637765085659 

Vì vậy, nếu bạn là sau màn trình diễn, có lẽ bạn nên sử dụng zip() mặc dù danh sách comprehensions là không quá xa phía sau. Hiệu suất của append thực sự là khá kém so với.

Các vấn đề liên quan