【问题标题】:Python Iterating on list using another listPython使用另一个列表迭代列表
【发布时间】:2020-06-18 19:10:58
【问题描述】:

我认为这很简单,但不适用于我。 我有 2 个列表:

a = [1, 3, 6]
b = [['A', 'B', 'C', 'D', 'E', 'F', 'G'],
     ['H', 'I', 'J', 'K', 'L', 'M', 'N'],
     ['O', 'P', 'Q', 'R', 'S', 'T', 'U']]

我需要使用 a 的元素遍历 b。

想要的输出是:

c = [['B', 'D', 'G'],
     ['I', 'K', 'N'],
     ['P', 'R', 'U']]

欢迎使用数组,有什么建议吗?

【问题讨论】:

标签: python arrays list


【解决方案1】:

我喜欢使用map对列表进行操作:

list(map(lambda x: [x[i] for i in a], b))
[['B', 'D', 'G'], ['I', 'K', 'N'], ['P', 'R', 'U']]

【讨论】:

    【解决方案2】:

    由于它的简短性、语义和无需额外的模块,我更喜欢嵌套列表理解:

    >>> [[l[i] for i in a] for l in b]
    [['B', 'D', 'G'], ['I', 'K', 'N'], ['P', 'R', 'U']]
    

    外部理解意味着'创建一个列表并将b 中的每个列表l 的内部理解结果添加到它。内部理解是“创建一个列表并为a 中的每个i 添加li-th 元素。”

    我注意到@norok2 测试了此选项的速度,但没有明确显示。

    【讨论】:

      【解决方案3】:

      您可以使用内置operator 模块中的itemgetter() 方法:

      from operator import itemgetter
      
      a = itemgetter(1, 3, 6)
      
      b = [['A', 'B', 'C', 'D', 'E', 'F', 'G'],
           ['H', 'I', 'J', 'K', 'L', 'M', 'N'],
           ['O', 'P', 'Q', 'R', 'S', 'T', 'U']]
      
      c = [list(a(l)) for l in b]
      
      print(c)
      

      输出:

      [['B', 'D', 'G'],
       ['I', 'K', 'N'],
       ['P', 'R', 'U']]
      

      【讨论】:

        【解决方案4】:

        如果a 应该索引到每个子列表中,您可以使用以下嵌套列表理解

        >>> [[sub[i] for i in a] for sub in b]
        [['B', 'D', 'G'],
         ['I', 'K', 'N'],
         ['P', 'R', 'U']]
        

        如果abnumpy.array 也可以

        >>> b[:, a]
        array([['B', 'D', 'G'],
               ['I', 'K', 'N'],
               ['P', 'R', 'U']], dtype='<U1')
        

        【讨论】:

          【解决方案5】:

          (假设预期的输出只是有一个错字。)

          最有效的通用方式是通过operator.itemgetter()

          from operator import itemgetter
          
          
          a = [1, 3, 6]
          
          b = [['A', 'B', 'C', 'D', 'E', 'F', 'G'],
               ['H', 'I', 'J', 'K', 'L', 'M', 'N'],
               ['O', 'P', 'Q', 'R', 'S', 'T', 'U']]
          
          c = [list(itemgetter(*a)(x)) for x in b]
          print(c)
          # [['B', 'D', 'G'], ['I', 'K', 'N'], ['P', 'R', 'U']]
          

          对于您的输入大小,转换为list 使其实际上与我系统上的双列表理解相当,但在其他方面更快。对于较大的a 大小,NumPy 实际上是最快的(尽管它要求b 的内部列表具有相同数量的元素,itemgetter 并不关心)。

          从我的测试系统中出来的一些时间:

          %timeit [[x[i] for i in a] for x in b]
          # 1000000 loops, best of 3: 1.14 µs per loop
          %timeit [list(itemgetter(*a)(x)) for x in b]
          # 1000000 loops, best of 3: 1.13 ns per loop
          %timeit [itemgetter(*a)(x) for x in b]
          # 1000000 loops, best of 3: 732 ns per loop
          %timeit np.array(b)[:, tuple(a)]
          # 100000 loops, best of 3: 6.84 µs per loop
          
          b = b * 1000000
          %timeit [[x[i] for i in a] for x in b]
          # 1 loop, best of 3: 1.19 s per loop
          %timeit [list(itemgetter(*a)(x)) for x in b]
          # 1 loop, best of 3: 1.15 s per loop
          %timeit [itemgetter(*a)(x) for x in b]
          # 1 loop, best of 3: 800 ms per loop
          %timeit np.array(b)[:, tuple(a)]
          # 1 loop, best of 3: 2.31 s per loop
          
          a = a * 100
          b = b * 10000
          %timeit [[x[i] for i in a] for x in b]
          # 1 loop, best of 3: 386 ms per loop
          %timeit [list(itemgetter(*a)(x)) for x in b]
          # 10 loops, best of 3: 193 ms per loop
          %timeit [itemgetter(*a)(x) for x in b]
          # 10 loops, best of 3: 171 ms per loop
          %timeit np.array(b)[:, tuple(a)]
          # 10 loops, best of 3: 63.1 ms per loop
          

          【讨论】:

            猜你喜欢
            • 2021-10-22
            • 2021-08-09
            • 1970-01-01
            • 2021-04-04
            • 2019-10-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多