【问题标题】:Iterating over multiple lists simultaneously in Python在 Python 中同时迭代多个列表
【发布时间】:2013-10-07 14:57:44
【问题描述】:

我想同时遍历两个列表。

第一个列表只是一个常规的元素列表。

第二个列表是一个包含多个列表的列表,每个列表都包含实际上是三元组的元素。

我想对第二个列表中每个列表中的每个 3 元组的每个元素执行一些功能(如果可以理解的话)。这个函数将依赖于第一个列表中的一个元素,我希望它全部按顺序运行。

ie:如果我有一些列表,例如 [0,1,2,3,1,5,6,7,1,2,3,5,1,1,2,3,5,6] 作为我的第一个列表,[[(13,12,32),(11,444,25)],[(312,443,12),(123,4,123)],[(545,541,1),(561,112,560)]] 作为我的第二个列表,我想执行这样的操作,使其涉及第一个列表的第一个元素和第二个列表的第一个列表的第一个元组的第一个元素。我希望使用第一个列表的第 n 个元素和元组的第 n 个元素来迭代此操作 bla bla

因此,如果我们正在查看哪些元素将一起用于操作:

  • 0 配 13
  • 1 配 12
  • 2 配 32
  • 3 配 11
  • 1 配 444
  • 5 配 25
  • 6配312

等等。

发生的事情是我的函数将从第二个列表中获取元素,从列表 1 中获取它的配对元素,以某种方式使用这些位,并输出一个新值来替换它原来的第二个列表对应项。然后我想构建一个替换/新的“第二个列表”,它是运行此函数后的第二个列表(它使用上述信息)

希望这是半连贯的,我试图尽可能提供信息。有什么不清楚的请询问。

干杯,感谢您提供的任何帮助!

编辑:

我想获取列表 1 和列表 2,然后展平列表 2。 然后我想使用一些函数遍历这两个列表。 然后我想构建一个新列表,它使用我的函数的输出,这将只是我扁平化的第二个列表的一些“调整后”值,但以它最初的格式,列表列表中的元组。

ie:我的输出可能是这样的:

[[(13,13,32),(11,444,24)],[(313,443,12),(123,4,123)],[(546,542,1),(561,112,561)]]

由于“通过”我的函数,一些值要么发生了一点变化,要么保持不变。

编辑#2:

勾选的解决方案准确地显示了这个问题需要什么!

编辑#3:

顶级解决方案所需的一些修复:
我将如何修复代码,以便如果第一个列表为空,则输出将只是原始的第二个列表? 如果第二个列表为空,则输出应该只是一个空列表。 此外,如果 len(list 1) > len(list 2),它将一直迭代到列表 2 的末尾,然后忽略列表 1 中的多余部分,输出与原始列表 2 格式相同的新列表。 如果 len(list 2) > len (list 1),它将只迭代列表 1 可以匹配的位置,但保持列表 2 的其余部分不变,而不是将其砍掉。

我可以使用一些 if/elseif/else 循环来执行所有这些修复吗?

编辑:我仍在寻求解决这些问题,这些问题可以被分离/假设为单独的查询。如果有人有兴趣帮忙,我在这里提出了一个新问题https://stackoverflow.com/questions/19118641/making-a-function-only-run-for-certain-conditions-in-python

【问题讨论】:

  • 听起来你真正想做的是 flatten 第二个列表,然后你可以例如zip 和第一个一起。
  • 因此,一旦我使用下面建议的方法之一展平了第二个列表,使用每个列表中的一个元素执行了我的操作,我将如何创建我的第二个列表的未展平替换/新版本我输出的数据?
  • 对于您给出的示例,您自己完成工作并向我们展示确切您想要最终得到的结果会有所帮助。

标签: python list loops


【解决方案1】:

这样做。

dict(zip(ListA, eval('[' + repr(ListB).replace('(', '').replace(')', \
'').replace('[', '').replace('[', '') + ']'))

我知道它很长,但它会返回一个包含您需要的输出的字典。

【讨论】:

    【解决方案2】:

    python 的itertools 包含izip,它允许您使用与 zip 相同的语法压缩任意数量的列表。即izip(l1, l2, l3)

    【讨论】:

      【解决方案3】:

      您可以像这样使用zipitertools.chain

      from itertools import chain
      
      first = [0, 1, 2, 3, 1, 5, 6, 7, 1, 2, 3, 5, 1, 1, 2, 3, 5, 6]
      second = [
          [(13, 12, 32), (11, 444, 25)],
          [(312, 443, 12), (123, 4, 123)],
          [(545, 541, 1), (561, 112, 560)]
      ]    
      zip(first, chain(*(chain(*second))))
      

      更新

      def add(x, y):
          return x + y
      
      # Flatten the second list
      second_flattened = list(chain(*(chain(*second))))
      
      # There is probably a better way to achieve this
      foo = [add(x, y) for x, y in zip(first, second_flattened)]
      
      # If second is longer we should append unprocessed values
      if len(second_flattened) > len(first):
          foo += second_flattened[len(foo): ]
      
      bar = [foo[i:i+3] for i in range(0, len(foo), 3)]
      second = [bar[i:i+2]  for i in range(0, len(foo) / 3, 2)]
      

      【讨论】:

      • 好的,所以如果我想说,从每个列表中取出元素,将它们配对在一起,在某个函数中使用它们,这将为我的新版本列表 2 提供一个元素,然后将这些输出放入新版本的列表 2 中,我怎么能做这样的任务?
      • 你真的尝试过代码吗?提示:zip 结果是可迭代的;尝试迭代它,看看你得到了什么。我不明白您所说的“放入新版本的列表 2”是什么意思。
      • 我做到了,而且我很好地迭代了 zip 函数(可能需要仔细检查语法)。我想使用我的函数的输出(它使用列表 1 中的数据和列表 2 的扁平版本)并以与列表 2 相同的格式构造一个新列表,但值是我的函数的输出。跨度>
      • 成功!你的编辑绝对完美。非常感谢!
      • 一些额外的查询:我将如何修复代码以便如果第一个列表为空,则输出将只是原始的第二个列表。如果第二个列表为空,则输出将只是一个空列表。此外,如果 len(list 1) > len(list 2),它将一直迭代到列表 2 的末尾,然后忽略列表 1 中的多余部分。如果 len(list 2) > len (list 1),它只会迭代列表 1 可以匹配的位置,但保留列表 2 的其余部分不变,而不是将其砍掉。
      【解决方案4】:

      您的第二个列表需要按两个级别展开:

      import itertools
      flatten = itertools.chain.from_iterable
      for i, j in zip(list1, flatten(flatten(list2))):
          # whatever
      

      【讨论】:

        【解决方案5】:

        您可以使用类似的方法从第二个列表中获取每个元素:

        from itertools import chain
        l=list(chain.from_iterable(list2))
        

        【讨论】:

          猜你喜欢
          • 2022-06-11
          • 1970-01-01
          • 1970-01-01
          • 2014-01-13
          • 2014-02-01
          • 1970-01-01
          • 2015-03-24
          • 1970-01-01
          • 2012-05-12
          相关资源
          最近更新 更多