python中的组合filter()无法按预期工作

时间:2019-04-14 09:39:55

标签: python

据我了解,以下代码应输出[['b']]。 而是输出[['a', 'exclude'], ['b']]

这是python中的错误,还是我误解了?

lists_to_filter = [
    ['a', 'exclude'],
    ['b']
]
# notice that when 'exclude' is the last element, the code returns the expected result
for exclude_label in ['exclude', 'something']:
    lists_to_filter = (labels_list for labels_list in lists_to_filter if exclude_label not in labels_list)
    # notice that changing the line above to the commented line below (i.e. expanding the generator to a list) 
    # will make the code output the expected result, 
    # i.e. the issue is only when using filter on another filter, and not on a list
    # lists_to_filter = [labels_list for labels_list in lists_to_filter if exclude_label not in labels_list]
lists_to_filter = list(lists_to_filter)
print(lists_to_filter)

2 个答案:

答案 0 :(得分:2)

之所以会这样,是因为lists_of_filter仅在循环之外进行迭代。在循环之外,您有exclude_label == 'something',这就是为什么您得到意外结果的原因。要对其进行检查,可以在行exclude_label = 'exclude'中放置

lists_to_filter = [
    ['a', 'exclude'],
    ['b']
]

for exclude_label in ['exclude', 'something']:
    lists_to_filter = (labels_list for labels_list in lists_to_filter if exclude_label not in labels_list)

exclude_label = 'exclude'
lists_to_filter = list(lists_to_filter)
print(lists_to_filter)  # [['b']]

doc for generator expressions说:“ 后续for子句和最左边的for子句中的任何过滤条件都不能在封闭范围内进行评估,因为它们可能取决于从最左边的可迭代项获得的值。”。在您的情况下,过滤条件if exclude_label ...取决于从for exclude_label in ...循环获得的值。

答案 1 :(得分:0)

因为您多次循环分配lists_to_filter,所以它只会返回最后一个结果。不包含'something'

中的最后一个元素['exclude', 'something']

您可以使用all来实现自己的目标:

lists_to_filter = [labels_list for labels_list in lists_to_filter if all(exclude_label not in labels_list for exclude_label in ['exclude', 'something'])]

或扩展all逻辑:

    result = []

    for labels_list in lists_to_filter:
        exclude = False
        for exclude_label in ['exclude', 'something']:
            if exclude_label in labels_list:
                exclude = True
        if not exclude:
            result.append(labels_list)

    print(result)

或者您可以根据标题使用filter

lists_to_filter = list(filter(lambda x: all(exclude_label not in x for exclude_label in exclude_labels), lists_to_filter))

输出:

[['b']]

希望对您有所帮助,如果还有其他问题,请发表评论。 :)