【问题标题】:List comprehension iterating over two lists is not working as expected [duplicate]遍历两个列表的列表理解没有按预期工作[重复]
【发布时间】:2019-06-22 13:59:06
【问题描述】:

我想遍历两个列表。第一个列表包含一些浏览器用户代理,第二个列表包含这些浏览器的版本。我只想过滤掉那些版本大于 60 的用户代理。

这是我的列表理解的样子:

[link for ver in version for link in useragents if ver > 60]

这个列表的问题是它多次打印同一个用户代理。我使用zip 函数编写了以下内容,效果很好:

for link, ver in zip(useragents, version):
    if ver > 60:
        # append to list
        print(link)

为什么我的列表理解返回了意外的结果?

【问题讨论】:

    标签: python list for-loop nested list-comprehension


    【解决方案1】:
    [link for (link, ver) in zip(useragents, version) if ver > 60]
    

    您仍然需要将两个列表压缩在一起。

    【讨论】:

      【解决方案2】:

      您的第一个列表理解相当于:

      res = []
      for ver in version:
          for link in useragents:
              if ver > 60:
                  res.append(link)
      

      请注意,您有时间复杂度为 O(n2) 的嵌套循环,即您正在迭代 version 的每个组合useragents。这不是您想要的,假设您的 versionuseragents 列表是对齐的。

      您的for 循环等效于以下列表理解:

      res = [link for link, ver in zip(useragents, version) if ver > 60]
      

      【讨论】:

        【解决方案3】:

        如果没有您的数据,无法确定发生了什么,但总的来说,“双重”列表理解与 zip 不同,而是一个双重循环,即

        [a for b in bs for a in as]
        

        等价于

        for b in bs:
            for a in as:
                lst.append(a)
        

        【讨论】:

          【解决方案4】:

          这个

          [link for ver in version for link in useragents if ver > 60]
          

          与 zip 不同。它不是并行遍历两个序列。它正在遍历这两个序列的所有组合。

          好像你写的:

          for ver in version:
              for link in useragents:
                  if ver > 60:
                      # append(link)
          

          因此,如果两个序列的长度均为 5,则将有 25 种组合(其中一些被条件 ver > 60 过滤掉)。

          当您想并行处理序列时,zip 是实现它的方法,即使在理解中也是如此。

          [link for (link, ver) in zip(useragents, version) if ver > 60]
          

          【讨论】:

            【解决方案5】:

            或者,您可以将函数compress()map() 结合使用,在其中检查一些条件:

            from itertools import compress
            
            filter_ = map(lambda x: x > 60, version)
            list(compress(useragents, filter_))
            

            示例:

            s = 'ABCDEFG'
            nums = range(len(s))
                
            filter_ = map(lambda x: x > 3, nums)
            print(list(compress(s, filter_)))
            # ['E', 'F', 'G']
            

            【讨论】:

              猜你喜欢
              • 2017-08-22
              • 2016-05-02
              • 1970-01-01
              • 1970-01-01
              • 2014-04-23
              • 2022-06-22
              • 1970-01-01
              相关资源
              最近更新 更多