已经有很多答案展示了如何正确实现这个任务,但没有一个讨论你的实际代码。
解构你的代码
希望这将有助于理解您的代码为何不起作用。这是您的代码,添加了 cmets:
def func(list1):
for i in range(len(list1)):
list2 = [x for x in list1 if x != list1[i]]
在这里您构造一个列表list2,其中不包含list1[i]。
if list1[i] in list2:
这个if 声明总是错误的,通过list2 的构造。
list1.remove(i)
即使您修复了if 语句的逻辑,list1.remove(i) 也会带来麻烦:尝试在迭代列表时删除列表元素会使其余迭代的索引无效。最好避免这样做,而是将结果构建到一个新列表中。
此外,list1.remove(i) 正在 list1 中寻找值 i,并将删除它,无论它首先找到它。正如这段代码所期望的那样,它并没有删除第 i 个元素。
return list1
而且这个 return 语句可能并不意味着缩进这么深,它应该与顶部的 for 语句处于同一级别。
工作代码更接近你的逻辑
虽然我认为这不是最好的解决方案 - 其他答案提供了更好的解决方案 - 这是一个受您的代码启发的解决方案,它有效。
def func(list1):
list2 = [] # We'll append elements here
for item in list1: # more pythonic way to loop over a list
if item not in list2:
list2.append(item)
return list2
我的首选解决方案
好的,所以现在我在其他答案中复制信息,但使用 Python 3.7(*) 或更新版本,dict 保证保持插入其中的元素的顺序,我会使用 @Pedro Maia 的解决方案:
def func(list1):
return list(dict.fromkeys(list1))
事实上,我最近在我的代码库中使用了这种技术。
在旧版本的 Python 中,字典没有顺序。但是,自 Python 2.7 以来,collections 库中一直存在 OrderedDict 类,因此此代码适用于任何版本的 Python >= 2.7:
from collections import OrderedDict
def func(list1):
return list(OrderedDict.fromkeys(list1))
如果您不熟悉它们,请查看collections library 和itertools library,它们为各种问题提供了非常有用的帮助。
(*) 根据collections.OrderedDict 的手册,Python dicts 只保证从 Python 3.7 开始订购,即使它们实际上是在 Python 3.6 中开始订购的,至少对于 CPython 实现是这样。另见:Are dictionaries ordered in Python 3.6+?