遍历两个列表的列表理解没有按预期工作[重复]

Posted

技术标签:

【中文标题】遍历两个列表的列表理解没有按预期工作[重复]【英文标题】: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)

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

【问题讨论】:

【参考方案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']

【讨论】:

以上是关于遍历两个列表的列表理解没有按预期工作[重复]的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:当“navigationBarItems”修改列表时,“listRowInsets”无法按预期工作[重复]

Django:如何遍历模板内的两个列表[重复]

ArrayAdapter 更新列表 - 没有按预期工作?

没有“for”的列表理解[重复]

Javascript FileSystem函数无法按预期工作[重复]

上下文菜单不适用于两个片段