问题:如何将元组列表转换为多个列表?

假设我有一个元组列表,并且我想转换为多个列表。

例如,元组列表是

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

Python中是否有任何内置函数可以将其转换为:

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

这可以是一个简单的程序。但是我只是对Python中存在这种内置函数感到好奇。

Suppose I have a list of tuples and I want to convert to multiple lists.

For example, the list of tuples is

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

Is there any built-in function in Python that convert it to:

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

This can be a simple program. But I am just curious about the existence of such built-in function in Python.


回答 0

内置功能zip()几乎可以满足您的需求:

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

唯一的区别是您得到元组而不是列表。您可以使用将它们转换为列表

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

The built-in function zip() will almost do what you want:

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

The only difference is that you get tuples instead of lists. You can convert them to lists using

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

回答 1

python docs

zip()与*运算符结合可用于解压缩列表:

具体的例子:

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

From the python docs:

zip() in conjunction with the * operator can be used to unzip a list:

Specific example:

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

Or, if you really want lists:

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

回答 2

用:

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

Use:

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

回答 3

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相比较而言,的效果实际上很差。

franklsf95 goes for performance in his answer and opts for list.append(), but they are not optimal.

Adding list comprehensions, I ended up with the following:

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

This gave the result:

zip:            122.11585397789766
append:         356.44876132614047
list comp:      144.637765085659

So if you are after performance, you should probably use zip() although list comprehensions are not too far behind. The performance of append is actually pretty poor in comparison.


回答 4

尽管使用的*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到4倍zip!测试脚本在这里:

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

Despite *zip being more Pythonic, the following code has much better performance:

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

Also, when the original list zs is empty, *zip will raise, but this code can properly handle.

I just ran a quick experiment, and here is the result:

Using *zip:     1.54701614s
Using append:   0.52687597s

Running it multiple times, append is 3x – 4x faster than zip! The test script is here:

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

回答 5

除了Claudiu的答案,您还可以使用:

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

根据@Peyman mohseni kiasari编辑

In addition to Claudiu’s answer, you can use:

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

Edited according to @Peyman mohseni kiasari


回答 6

添加到Claudiu和Claudiu的答案中,并且由于需要在python 3中从itertools导入map,因此您还可以使用以下列表推导:

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

Adding to Claudiu’s and Claudiu’s answer and since map needs to be imported from itertools in python 3, you also use a list comprehension like:

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

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。