如何从列表中删除所有重复项

如何使用 python 检查列表并删除所有副本?我不想指定重复的项目是什么-我希望代码找出是否有,并删除他们,如果有的话,只保留一个实例的每个。如果列表中有多个重复项,它也必须工作。

例如,在我下面的代码中,列表 lsecatedOrbList 有12个项——一个重复6次,一个重复5次,并且只有一个实例。我希望它改变列表,这样就只有三个项目-每个项目之一,并在相同的顺序,他们出现之前。我试过了:

for i in lseparatedOrbList:
for j in lseparatedOrblist:
if lseparatedOrbList[i] == lseparatedOrbList[j]:
lseparatedOrbList.remove(lseparatedOrbList[j])

但我得到了一个错误:

Traceback (most recent call last):
File "qchemOutputSearch.py", line 123, in <module>
for j in lseparatedOrblist:
NameError: name 'lseparatedOrblist' is not defined

我猜是因为我试图在循环的时候循环 lsecatedOrbList,但是我想不出其他的方法。

226712 次浏览

使用 set():

woduplicates = set(lseparatedOrblist)

返回一个没有重复的集合。如果由于某种原因,需要返回一个列表:

woduplicates = list(set(lseperatedOrblist))

但是,这将有一个 顺序不同比您的原始列表。

其实是因为你少了一个大写字母。

故意装模作样:

for i in lseparatedOrbList:   # capital 'L'
for j in lseparatedOrblist:   # lowercase 'l'

尽管更有效的方法是将内容插入到 set中。

如果维护列表顺序很重要(例如,它必须是“稳定的”) ,则 查看这个问题的答案

这个应该对你有用:

new_list = list(set(old_list))

set将自动删除重复项。 list将把它强制转换回一个列表。

只要创建一个要填充的新列表,如果您的列表的项目还没有在新列表中输入它,那么只需移动到原始列表中的下一个项目。

for i in mylist:
if i not in newlist:
newlist.append(i)

你可以这样做:

x = list(set(x))

例如: 如果你这样做:

x = [1,2,3,4,5,6,7,8,9,10,2,1,6,31,20]
x = list(set(x))
x

你会看到以下结果:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 31]

您应该考虑的只有一件事: 生成的列表不会像原始列表那样排序(将在流程中丢失顺序)。

不,这只是个打印错误,末尾的“列表”必须大写。您可以在同一个变量上嵌套循环(尽管很少有理由这样做)。

但是,代码还有其他问题。对于初学者来说,您将遍历列表,因此 ij将是项而不是索引。此外,在迭代一个集合时,您不能更改它(好吧,您“可以”这么做,因为它运行,但是疯狂就在于此——例如,您可能会跳过项目)。然后是复杂性问题,你的代码是 O (n ^ 2)。要么将列表转换为 set,然后返回到 list(简单,但要对剩余的列表项进行洗牌) ,要么执行下面的操作:

seen = set()
new_x = []
for x in xs:
if x in seen:
continue
seen.add(x)
new_xs.append(x)

两种解决方案都要求项是散列的。如果这不可能,您可能必须坚持目前的方法,而不考虑上面提到的问题。

这应该更快,并将保持原有的秩序:

seen = {}
new_list = [seen.setdefault(x, x) for x in my_list if x not in seen]

如果你不在乎秩序,你可以:

new_list = list(set(my_list))

因为它不会对已经检查的条目进行迭代,所以速度更快。

def purge_dublicates(X):
unique_X = []
for i, row in enumerate(X):
if row not in X[i + 1:]:
unique_X.append(row)
return unique_X

维持秩序的现代方法是:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(lseparatedOrbList))

正如 Raymond Hettinger 所讨论的。在 python 3.5及以上版本中,这也是最快的方法——详情请参阅链接答案。然而,键必须是散列的(就像你的列表中的情况我认为)


在 python 3.7命令 dicts 是一种语言特征时,上面的调用变成

>>> list(dict.fromkeys(lseparatedOrbList))

演出:

"""Dedup list."""
import sys
import timeit


repeat = 3
numbers = 1000


setup = """"""
def timer(statement, msg='', _setup=None):
print(msg, min(
timeit.Timer(statement, setup=_setup or setup).repeat(
repeat, numbers)))


print(sys.version)
s = """import random; n=%d; li = [random.randint(0, 100) for _ in range(n)]"""
for siz, m in ((150, "\nFew duplicates"), (15000, "\nMany duplicates")):
print(m)
setup = s % siz
timer('s = set(); [i for i in li if i not in s if not s.add(i)]', "s.add(i):")
timer('list(dict.fromkeys(li))', "dict:")
timer('list(set(li))', 'Not order preserving: list(set(li)):')

提供:

3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)]


Few duplicates
s.add(i): 0.008242200000040611
dict: 0.0037373999998635554
Not order preserving: list(set(li)): 0.0029409000001123786


Many duplicates
s.add(i): 0.2839437000000089
dict: 0.21970469999996567
Not order preserving: list(set(li)): 0.102068700000018

因此,尽管用 set.add 处理许多重复的列表内涵似乎一直更快,但不确定进一步改变这些数字是否会得到不同的结果。list(set)当然更快,但不保留原始列表顺序,这是这里的一个要求

有一个更快的解决办法:

list = [1, 1.0, 1.41, 1.73, 2, 2, 2.0, 2.24, 3, 3, 4, 4, 4, 5, 6, 6, 8, 8, 9, 10]
list2=[]


for value in list:
try:
list2.index(value)
except:
list2.append(value)
list.clear()
for value in list2:
list.append(value)
list2.clear()
print(list)
print(list2)

通过这种方式,人们可以删除列表中多次出现的特定项目: 尝试删除所有5个

list1=[1,2,3,4,5,6,5,3,5,7,11,5,9,8,121,98,67,34,5,21]
print list1
n=input("item to be deleted : " )
for i in list1:
if n in list1:
list1.remove(n)
print list1