Python:如何从列表中删除所有重复的项目

lap*_*ian 38 python list

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

例如,在我的下面的代码中,列表lseparatedOrbList有12个项目 - 一个重复六次,一个重复五次,并且只有一个实例.我希望它改变列表,因此只有三个项目 - 每个项目中的一项,并且它们之前出现的顺序相同.我试过这个:

for i in lseparatedOrbList:
   for j in lseparatedOrblist:
        if lseparatedOrbList[i] == lseparatedOrbList[j]:
            lseparatedOrbList.remove(lseparatedOrbList[j])
Run Code Online (Sandbox Code Playgroud)

但我得到错误:

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

我猜是因为这是因为我试图循环通过lseparatedOrbList而我循环通过它,但我想不出另一种方法来做到这一点.

Jac*_*cob 82

用途set():

woduplicates = set(lseparatedOrblist)
Run Code Online (Sandbox Code Playgroud)

返回没有重复项的集合.如果您出于某种原因需要列表:

woduplicates = list(set(lseperatedOrblist))
Run Code Online (Sandbox Code Playgroud)

  • 您还应该明确指出,这不会保留元素顺序. (19认同)
  • 值得注意的是,如果列表中有列表或集合,则会失败. (15认同)
  • 这不适用于所有情况,例如不适用于字典列表 (2认同)

Jon*_*nde 77

只需填写一个新列表,如果列表中的项目尚未在新列表中输入,则只需转到原始列表中的下一个项目即可.

for i in mylist:
  if i not in newlist:
    newlist.append(i)
Run Code Online (Sandbox Code Playgroud)

我认为这是正确的语法,但我的python有点不稳定,我希望你至少得到这个想法.

  • 好,我想我没有忘记我所有的蟒蛇,它只有两年.就像一句警告,我很确定这是一个O(n ^ 2)操作,所以你可能不想在大型列表上使用它(例如10,000个项目).如果你需要它用于大型列表,我会创建一个哈希表来检查(O(1),产生一个整体O(n)实现),而不是检查列表,但如果你正在处理大型列表,我也许不想使用python. (8认同)
  • 创建一个集合搞砸了订单 (3认同)
  • 正确的方法是使用set(),请参阅下面的cilaris的答案. (2认同)
  • 你是什​​么意思这不正确的方法?这可以完成所要求的工作,而无需创建任何设置的任何开销. (2认同)
  • 这样既可以保持顺序,也可以用于非哈希列表项,这是一个加号。 (2认同)

Tad*_*eck 29

你可以这样做:

x = list(set(x))
Run Code Online (Sandbox Code Playgroud)

示例:如果您执行类似的操作:

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

你会看到以下结果:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 31]
Run Code Online (Sandbox Code Playgroud)

您应该只考虑一件事:结果列表不会作为原始列表排序(在此过程中将丢失订单).

  • 如果原始列表 `x` 包含列表,则不起作用 (4认同)

Pao*_*tti 20

这应该更快,并将保留原始顺序:

seen = {}
new_list = [seen.setdefault(x, x) for x in my_list if x not in seen]
Run Code Online (Sandbox Code Playgroud)

如果您不关心订单,您可以:

new_list = list(set(my_list))
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的答案,因为它既考虑保序又不考虑保序。 (2认同)

Mr_*_*s_D 11

保持秩序的现代方法是:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(lseparatedOrbList))
Run Code Online (Sandbox Code Playgroud)

正如 Raymond Hettinger在这个答案中所讨论的那样。在 python 3.5 及更高版本中,这也是最快的方法 - 有关详细信息,请参阅链接的答案。但是,键必须是可散列的(我认为在您的列表中就是这种情况)


从 python 3.7 开始,有序字典是一个语言特性,所以上面的调用变成

>>> list(dict.fromkeys(lseparatedOrbList))
Run Code Online (Sandbox Code Playgroud)

表现:

"""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)):')
Run Code Online (Sandbox Code Playgroud)

给出:

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
Run Code Online (Sandbox Code Playgroud)

因此 dict 似乎始终更快,尽管使用 set.add 对许多重复项进行列表理解 - 不确定进一步改变数字是否会产生不同的结果。list(set)当然更快,但不保留原始列表顺序,这是这里的要求


小智 7

不,这只是一个错字,最后的"清单"必须大写.您可以将循环嵌套在同一个变量上(尽管很少有理由).

但是,代码还有其他问题.对于初学者来说,你是在迭代列表,所以i并且j将是项目而不是索引.此外,你不能在迭代它时改变一个集合(好吧,你可以"运行",但疯狂就是这样 - 例如,你可以跳过项目).然后是复杂性问题,你的代码是O(n ^ 2).要么将列表转换set为a list又将其转换为(简单,但将剩余的列表项随机播放)或执行以下操作:

seen = set()
new_x = []
for x in xs:
    if x in seen:
        continue
    seen.add(x)
    new_xs.append(x)
Run Code Online (Sandbox Code Playgroud)

两种解决方案都要求物品可以清洗.如果那是不可能的,你可能不得不坚持你目前的方法没有提到的问题.


Man*_*y D 6

这应该为你做:

new_list = list(set(old_list))
Run Code Online (Sandbox Code Playgroud)

set将自动删除重复项.list将它扔回列表.

  • 如果原始列表`x`包含列表,则不起作用 (5认同)

Dan*_*olo 5

实际上,这是因为您缺少一个大写字母。

故意凹陷:

for i in lseparatedOrbList:   # capital 'L'
for j in lseparatedOrblist:   # lowercase 'l'
Run Code Online (Sandbox Code Playgroud)

虽然更有效的方法是将内容插入到set.

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


归档时间:

查看次数:

154764 次

最近记录:

7 年,5 月 前