为什么列表理解不能过滤掉重复项?

时间:2012-07-16 13:51:54

标签: python list filter duplicates list-comprehension

我对以下问题有一个解决方法。该解决方法将是一个for循环,其中包含一个包含在输出中的测试,如下所示:

#!/usr/bin/env python

def rem_dup(dup_list):
    reduced_list = []
    for val in dup_list:
        if val in reduced_list:
            continue
        else:
            reduced_list.append(val)

    return reduced_list

我问的是以下问题,因为我很想知道是否有列表理解解决方案。

鉴于以下数据:

reduced_vals = []
vals = [1, 2, 3, 3, 2, 2, 4, 5, 5, 0, 0]

为什么

reduced_vals = = [x for x in vals if x not in reduced_vals]

生成相同的列表?

>>> reduced_vals
[1, 2, 3, 3, 2, 2, 4, 5, 5, 0, 0]

我认为这与检查输出(reduced_vals)作为列表赋值的一部分有关。我很好奇,但确切的原因。

谢谢。

5 个答案:

答案 0 :(得分:6)

列表推导创建一个新列表,而reduced_vals在评估列表推导期间始终指向空列表。

Python中赋值的语义是:评估右侧并将结果对象绑定到左侧的名称。对裸名称​​从不的赋值会改变任何对象。

顺便说一下,您应该使用set()collections.OrderedDict.fromkeys()以有效的方式删除重复项(取决于您是否需要保留订单)。

答案 1 :(得分:4)

您正在测试一个空列表。

在将表达式赋值为reduced_vals的新值之前,首先对该表达式进行全面计算,因此在计算完整列表表达式之前,该表达式将保持为空。

换句话说,表达式[x for x in vals if x not in reduced_vals]是独立执行的。如果您以稍微修改的方式查看代码,它可能会有所帮助:

temp_var = [x for x in vals if x not in reduced_vals]
reduced_vals = temp_var
del temp_var

以上是直接将列表表达式的结果分配给reduced_vals的道德等价物,但我更明确地将使用第二个变量分配结果。

答案 2 :(得分:4)

在这一行:[x for x in vals if x not in reduced_vals] reduced_vals中没有一个的值,因为reduced_vals是空列表[]。换句话说,没有任何内容被过滤,vals中的所有元素都会被返回。

如果您尝试这样做:

[x for x in vals if x in reduced_vals]

结果是空列表[],因为 all {em}中的值不是(它是空的)。我相信你对列表理解中过滤部分的工作方式感到困惑:你看,过滤器只选择那些使条件成为reduced_vals的值,但它不会阻止重复值。

现在,如果你需要的是过滤掉重复项,那么列表理解就不适合这项工作。为此,使用一个集合 - 虽然它不一定会保留原始列表的顺序,但它将保证元素是唯一的:

True

答案 3 :(得分:1)

因为在构建整个列表之前,列表推导中的元素未分配给reduced_vals。如果您想使其工作,请使用for循环.append()

答案 4 :(得分:0)

因为在评估列表理解期间reduced_vals没有改变。