5

我有以下问题的解决方法。该解决方法将是一个 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) 作为分配给列表的一部分进行检查有关。我很好奇,但确切的原因。

谢谢你。

4

5 回答 5

6

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

Python 中赋值的语义是:计算右侧并将结果对象绑定到左侧的名称。对裸名的赋值永远不会改变任何对象。

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

于 2012-07-16T13:53:54.953 回答
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,但我通过使用第二个变量更清楚地分开分配结果。

于 2012-07-16T13:54:06.280 回答
4

在这一行中:[x for x in vals if x not in reduced_vals]没有一个值不在in 中reduced_valsreduced_vals空列表也是如此[]。换句话说,没有任何内容被过滤,并且所有元素都vals被返回。

如果你试试这个:

[x for x in vals if x in reduced_vals]

结果是空列表[],因为所有都不reduced_vals其中(为空)。我相信您对过滤部分在列表理解中的工作方式感到困惑:您会看到,过滤器仅选择那些构成条件的值True,但它不会防止重复值。

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

vals = [1, 2, 3, 3, 2, 2, 4, 5, 5, 0, 0]
list(set(vals))
> [0, 1, 2, 3, 4, 5]
于 2012-07-16T13:54:07.030 回答
1

因为列表推导式中的元素在reduced_vals整个列表构建完成之前不会被分配。如果您想完成这项工作,请使用for循环。.append()

于 2012-07-16T13:53:56.723 回答
0

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

于 2012-07-16T13:54:45.833 回答