列表理解不会消除重复项

  • 本文关键字:列表 python
  • 更新时间 :
  • 英文 :

a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
new_list = []
new_list.append([num for num in a+b if num not in new_list])
print(new_list)

输出:

[[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]]

为什么这段代码会产生重复项,而不是像set()那样产生一个没有重复项的所有数字的列表?

new_list = []
new_list.append([num for num in a+b if num not in new_list])

有几件事会阻止它工作。

  1. 将一个列表中的元素添加到另一个列表中,使用extend而不是appendappend整个列表附加到输入列表中,而不是添加单个元素。

  2. 即使您将其更改为extend,列表推导式中的所有项目在添加到new_list之前都会生成。它们不会一个接一个地添加,因此not in new_list检查不会看到以前迭代中的项。它将对空的new_list进行检查。

这种习惯用法实际上只适用于显式循环。我猜你是这样开始的:

new_list = []
for num in a+b:
if num not in new_list:
new_list.append(num)

这种类型的循环不能很好地转换为列表推导式,因为它具有自我依赖性。循环依赖于之前迭代的结果。

如果使用extend而不是append,使用迭代器而不是列表作为形参,就可以了:

new_list.extend(num for num in a+b if num not in new_list)

通过使用迭代器作为形参,可以随时更新new_list的内容,因此推导式中的条件可以访问到目前为止列表的内容。当你有一个列表作为参数时,在更新new_list之前,整个参数都会被求值,所以new_list在推导过程中保持为空,并且条件永远不会找到之前的元素(尚未添加的元素)

请注意,这是一种跳过重复值的低效方法,因为当列表被填满时,检查现有值所需的时间越来越长,导致时间复杂度为O(n^2)。你应该使用集合而不是列表。

您可以通过使用列表推导来实现,但严格考虑执行它的副作用:

a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
new_list = []
[new_list.append(num) for num in a+b if num not in new_list]
print(new_list)  # -> [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 4, 6, 7, 9, 10, 11, 12]

如果您不喜欢构建一个立即被丢弃的列表,这里有一个替代方案,它使用生成器表达式和内置的any()函数来消费它:

a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
new_list = []
any((new_list.append(num) for num in a+b if num not in new_list))
print(new_list)  # -> [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 4, 6, 7, 9, 10, 11, 12]

相关内容

  • 没有找到相关文章

最新更新