【问题标题】:Splitting a list of sequences into two lists efficiently [duplicate]有效地将序列列表拆分为两个列表[重复]
【发布时间】:2012-12-04 21:46:46
【问题描述】:

可能重复:
A Transpose/Unzip Function in Python

我有一个序列列表,每个序列有两个项目。我想把它变成两个列表。

catalog = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]

现在我只是这样做:

names = []
vals = []

for product in catalog:
        names.append(product[0])
        vals.append(product[1])

print (names)
print (vals)

输出两个列表,效果很好:

['abc', 'foo', 'bar', 'test']
['123', '456', '789', '1337']

有没有一种更简洁、更“pythonic”的方式来做到这一点?还是我应该坚持我所拥有的?欢迎任何有关编程风格的更正或反馈,我是新手,正在努力学习最佳实践。

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:
    >>> catalog = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]
    >>> names, vals = zip(*catalog)
    >>> names
    ('abc', 'foo', 'bar', 'test')
    >>> vals
    ('123', '456', '789', '1337')
    

    这里的*catalog 语法称为Unpacking Argument Listszip(*catalog) 转换为调用zip(catalog[0], catalog[1], catalog[2], ...)

    zip() 内置函数按索引对可迭代对象进行分组,因此当您像上面那样传递一堆二元素元组时,您会得到一个二元元组列表,其中第一个元组包含来自 @ 的每个元组的第一个元素987654329@,第二个元组包含来自catalog的每个元组的第二个元素。

    在快速测试中,zip() 版本在我测试 1,000,000 对时优于循环方法:

    In [1]: catalog = [(i, i+1) for i in range(1000000)]
    
    In [2]: def with_zip():
       ...:     return zip(*catalog)
       ...: 
    
    In [3]: def without_zip():
       ...:     names, vals = [], []
       ...:     for name, val in catalog:
       ...:         names.append(name)
       ...:         vals.append(val)
       ...:     return names, vals
       ...: 
    
    In [4]: %timeit with_zip()
    1 loops, best of 3: 176 ms per loop
    
    In [5]: %timeit without_zip()
    1 loops, best of 3: 250 ms per loop
    

    【讨论】:

    • 这太完美了,谢谢!我以前从未听说过这个功能。我正在链接到此功能的文档,以供未来的读者阅读。 docs.python.org/3.3/library/functions.html#zip
    • 它简洁明了,但它是否高效?在任何其他语言中,创建无数个参数都是可怕的。
    • @MarkRansom -- 我有时也想知道...
    • 嗯。我的结果不同——我得到zip ~ 490 ms,without_zip ~ 326 ms,而手动[c[0] for c in catalog]/[c[1] etc.] 只有 205。[itemgetter 似乎与 listcomp 相当。] 我倾向于忽略顺序统一的因素,不过,所以我可能会自己使用zip,不管速度如何。
    【解决方案2】:

    当然,使用这个:

    lst = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]
    tup1, tup2 = zip(*lst)
    

    上面将返回一对带有元素的元组。如果你需要 lists,那么使用这个:

    lst = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]
    lst1, lst2 = map(list, zip(*lst))
    

    【讨论】:

    • 一个元组可以满足我的使用,但感谢您的彻底!
    猜你喜欢
    • 2012-10-20
    • 2021-12-31
    • 2022-08-09
    • 2018-05-26
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 2019-06-28
    • 1970-01-01
    相关资源
    最近更新 更多