【问题标题】:How to convert list of tuples to multiple lists?如何将元组列表转换为多个列表?
【发布时间】:2011-12-26 06:18:07
【问题描述】:

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

例如,元组的列表是

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

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

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

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

【问题讨论】:

    标签: python list tuples


    【解决方案1】:

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

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

    唯一的区别是你得到的是元组而不是列表。您可以使用

    将它们转换为列表
    list(map(list, zip(*[(1, 2), (3, 4), (5, 6)])))
    

    【讨论】:

    • 在Python中,需要将生成的迭代器转换成列表才能看到内容:list(zip(*[(1, 2), (3, 4), (5, 6)])).
    • @MERose 这个答案是为 Python 2 编写的。回到那天 zip()map() 返回列表,而不是像在 Python 3 中那样的惰性迭代器。我会更新答案。
    • 我知道我知道。我的评论是为了避免今天的观众感到困惑。另外,我忘了写“Python 3”。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      用途:

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

      【讨论】:

        【解决方案4】:

        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 的表现其实很差。

        【讨论】:

          【解决方案5】:

          尽管*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
          

          多次运行,appendzip 快 3 到 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.
          

          【讨论】:

            【解决方案6】:

            除了克劳迪乌的回答,你还可以使用:

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

            根据@Peyman mohseni kiasari 编辑

            【讨论】:

            • 不!它会给你(1, 3, 5)(2, 4, 6) 而不是列表。你应该使用map(list, zip(*[(1, 2), (3, 4), (5, 6)]))
            【解决方案7】:

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-06-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-12-11
              • 2012-06-05
              相关资源
              最近更新 更多