删除列表中的重复项

如何检查列表是否有重复项并返回没有重复项的新列表?

2039981 次浏览

获取唯一项集合的常见方法是使用#0。集合是不同对象的无序集合。要从任何可迭代对象创建集合,您只需将其传递给内置的#1函数。如果您稍后再次需要真实列表,您可以类似地将集合传递给#2函数。

以下示例应涵盖您尝试执行的任何操作:

>>> t = [1, 2, 3, 1, 2, 3, 5, 6, 7, 8]>>> list(set(t))[1, 2, 3, 5, 6, 7, 8]>>> s = [1, 2, 3]>>> list(set(t) - set(s))[8, 5, 6, 7]

如上所述,集合本身是无序集合,因此顺序丢失。将集合转换回列表时,会创建任意顺序。

维持秩序

如果顺序对你很重要,那么你将不得不使用不同的机制。一个非常常见的解决方案是依靠#0在插入过程中保持键的顺序:

>>> from collections import OrderedDict>>> list(OrderedDict.fromkeys(t))[1, 2, 3, 5, 6, 7, 8]

从Python 3.7开始,内置字典也保证保持插入顺序,因此如果您使用Python 3.7或更高版本(或CPython 3.6),也可以直接使用它:

>>> list(dict.fromkeys(t))[1, 2, 3, 5, 6, 7, 8]

请注意,这可能会有一些开销,首先创建字典,然后从中创建列表。如果你实际上不需要保留顺序,你通常最好使用集合,特别是因为它给你更多的操作来处理。查看这个问题以获取更多详细信息和删除重复项时保留顺序的替代方法。


最后请注意,setOrderedDict/dict解决方案都要求您的项目为可散列。这通常意味着它们必须是不可变的。如果您必须处理不可散列的项目(例如列表对象),那么您将不得不使用缓慢的方法,基本上您必须将每个项目与嵌套循环中的每个其他项目进行比较。

如果你不在乎顺序,只要这样做:

def remove_duplicates(l):return list(set(l))

保证set没有重复项。

这是一个单行代码:list(set(source_list))会起作用。

set是不可能有重复的东西。

更新:订单保持方法是两行:

from collections import OrderedDictOrderedDict((x, True) for x in source_list).keys()

这里我们使用OrderedDict记住键的插入顺序,并且在特定键的值更新时不会更改它。我们将True作为值插入,但我们可以插入任何东西,值只是不被使用。(set的工作方式很像dict,也忽略了值。)

在python2.7,从可迭代对象中删除重复项同时保持原始顺序的新方法是:

>>> from collections import OrderedDict>>> list(OrderedDict.fromkeys('abracadabra'))['a', 'b', 'r', 'c', 'd']

在python3.5,OrderedDlic有一个C实现。我的时间显示,这现在是Python 3.5的各种方法中最快和最短的。

在python3.6,常规字典变得有序和紧凑。(此功能适用于CPython和PyPy,但可能不存在于其他实现中)。这为我们提供了一种新的最快的消重方法,同时保持顺序:

>>> list(dict.fromkeys('abracadabra'))['a', 'b', 'r', 'c', 'd']

在python3.7,保证在所有实现中都有序。因此,最短和最快的解决方案是:

>>> list(dict.fromkeys('abracadabra'))['a', 'b', 'r', 'c', 'd']

尝试使用集合:

import setst = sets.Set(['a', 'b', 'c', 'd'])t1 = sets.Set(['a', 'b', 'c'])
print t | t1print t - t1
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]>>> t[1, 2, 3, 1, 2, 5, 6, 7, 8]>>> s = []>>> for i in t:if i not in s:s.append(i)>>> s[1, 2, 3, 5, 6, 7, 8]

另一种做法:

>>> seq = [1,2,3,'a', 'a', 1,2]>> dict.fromkeys(seq).keys()['a', 1, 2, 3]

我的列表中有一个字典,所以我不能使用上述方法。我得到了错误:

TypeError: unhashable type:

因此,如果您关心命令和/或某些项目是无法。那么您可能会发现这很有用:

def make_unique(original_list):unique_list = [][unique_list.append(obj) for obj in original_list if obj not in unique_list]return unique_list

有些人可能认为带有副作用的列表理解不是一个好的解决方案。这里有一个替代方案:

def make_unique(original_list):unique_list = []map(lambda x: unique_list.append(x) if (x not in unique_list) else False, original_list)return unique_list

这是一个例子,返回列表没有重复保留顺序。不需要任何外部导入。

def GetListWithoutRepetitions(loInput):# return list, consisting of elements of list/tuple loInput, without repetitions.# Example: GetListWithoutRepetitions([None,None,1,1,2,2,3,3,3])# Returns: [None, 1, 2, 3]
if loInput==[]:return []
loOutput = []
if loInput[0] is None:oGroupElement=1else: # loInput[0]<>NoneoGroupElement=None
for oElement in loInput:if oElement<>oGroupElement:loOutput.append(oElement)oGroupElement = oElementreturn loOutput

也有使用Pandas和Numpy的解决方案。它们都返回numpy数组,因此如果您想要列表,则必须使用函数#0

t=['a','a','b','b','b','c','c','c']t2= ['c','c','b','b','b','a','a','a']

熊猫解决方案

使用Pandas函数#0

import pandas as pdpd.unique(t).tolist()>>>['a','b','c']pd.unique(t2).tolist()>>>['c','b','a']

Numpy溶液

使用numpy函数#0

import numpy as npnp.unique(t).tolist()>>>['a','b','c']np.unique(t2).tolist()>>>['a','b','c']

请注意,numpy.unique()也对值进行排序。因此列表t2返回排序。如果您想保留顺序,请使用这个答案

_, idx = np.unique(t2, return_index=True)t2[np.sort(idx)].tolist()>>>['c','b','a']

与其他解决方案相比,该解决方案并不那么优雅,但是,与pandas.unique()相比,numpy.unique()还允许您检查嵌套数组在一个选定轴上是否唯一。

创建一个新列表,保留L中重复项的第一个元素的顺序:

newlist = [ii for n,ii in enumerate(L) if ii not in L[:n]]

例如:如果L = [1, 2, 2, 3, 4, 2, 4, 3, 5],那么newlist将是[1, 2, 3, 4, 5]

这将检查每个新元素在添加之前没有出现在列表中。它也不需要进口。

这个关心顺序而不会有太多麻烦(OrderdDICT和其他)。可能不是最Pythonic的方式,也不是最短的方式,但确实有技巧:

def remove_duplicates(item_list):''' Removes duplicate items from a list '''singles_list = []for element in item_list:if element not in singles_list:singles_list.append(element)return singles_list

一位同事今天将接受的答案作为他代码的一部分发送给我进行代码审查。虽然我当然钦佩这个问题答案的优雅,但我对这个表现不满意。我已经尝试过这个解决方案(我使用来减少查找时间)

def ordered_set(in_list):out_list = []added = set()for val in in_list:if not val in added:out_list.append(val)added.add(val)return out_list

为了比较效率,我使用了100个整数的随机样本-62个是唯一的

from random import randintx = [randint(0,100) for _ in xrange(100)]
In [131]: len(set(x))Out[131]: 62

这是测量的结果

In [129]: %timeit list(OrderedDict.fromkeys(x))10000 loops, best of 3: 86.4 us per loop
In [130]: %timeit ordered_set(x)100000 loops, best of 3: 15.1 us per loop

那么,如果将set从溶液中移除会发生什么?

def ordered_set(inlist):out_list = []for val in inlist:if not val in out_list:out_list.append(val)return out_list

结果没有订单号那么糟糕,但仍然是原始解决方案的3倍以上

In [136]: %timeit ordered_set(x)10000 loops, best of 3: 52.6 us per loop

简单易行:

myList = [1, 2, 3, 1, 2, 5, 6, 7, 8]cleanlist = [][cleanlist.append(x) for x in myList if x not in cleanlist]

输出:

>>> cleanlist[1, 2, 3, 5, 6, 7, 8]

通过排序保存减少变体:

假设我们有列表:

l = [5, 6, 6, 1, 1, 2, 2, 3, 4]

减少变量(无效):

>>> reduce(lambda r, v: v in r and r or r + [v], l, [])[5, 6, 1, 2, 3, 4]

5倍更快但更复杂

>>> reduce(lambda r, v: v in r[1] and r or (r[0].append(v) or r[1].add(v)) or r, l, ([], set()))[0][5, 6, 1, 2, 3, 4]

说明:

default = (list(), set())# user list to keep order# use set to make lookup faster
def reducer(result, item):if item not in result[1]:result[0].append(item)result[1].add(item)return result
reduce(reducer, l, default)[0]

下面的代码是简单的删除重复列表

def remove_duplicates(x):a = []for i in x:if i not in a:a.append(i)return a
print remove_duplicates([1,2,2,3,3,4])

返回[1,2,3,4]

要删除重复项,请将其设为SET,然后再次将其设为LIST并打印/使用它。一个集合保证有唯一的元素。例如:

a = [1,2,3,4,5,9,11,15]b = [4,5,6,7,8]c=a+bprint cprint list(set(c)) #one line for getting unique elements of c

输出如下(在python 2.7中检查)

[1, 2, 3, 4, 5, 9, 11, 15, 4, 5, 6, 7, 8]  #simple list addition with duplicates[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15] #duplicates removed!!

还有许多其他答案建议使用不同的方法来执行此操作,但它们都是批处理操作,其中一些会丢弃原始顺序。这可能没问题,取决于你需要什么,但是如果你想按照每个值的第一个实例的顺序迭代值,并且你想动态删除重复项而不是一次全部删除,你可以使用这个生成器:

def uniqify(iterable):seen = set()for item in iterable:if item not in seen:seen.add(item)yield item

这将返回一个生成器/迭代器,因此您可以在任何可以使用迭代器的地方使用它。

for unique_item in uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]):print(unique_item, end=' ')
print()

输出:

1 2 3 4 5 6 7 8

如果你想要一个list,你可以这样做:

unique_list = list(uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]))
print(unique_list)

输出:

[1, 2, 3, 4, 5, 6, 7, 8]

如果您想删除重复项(就地编辑而不是返回新列表)而不使用内置的set、dict.keys、uniqify、计数器,请选中此项

>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]>>> for i in t:...     if i in t[t.index(i)+1:]:...         t.remove(i)...>>> t[3, 1, 2, 5, 6, 7, 8]

到目前为止,我在这里看到的所有保持顺序的方法要么使用朴素比较(充其量是O(n^2)时间复杂度),要么使用重量级OrderedDicts/set+list组合,这些组合仅限于可散列输入。这是一个独立于哈希的O(nlo爱人)解决方案:

更新添加了key参数,留档和Python 3兼容性。

# from functools import reduce <-- add this import on Python 3
def uniq(iterable, key=lambda x: x):"""Remove duplicates from an iterable. Preserves order.:type iterable: Iterable[Ord => A]:param iterable: an iterable of objects of any orderable type:type key: Callable[A] -> (Ord => B):param key: optional argument; by default an item (A) is discardedif another item (B), such that A == B, has already been encountered and taken.If you provide a key, this condition changes to key(A) == key(B); the callablemust return orderable objects."""# Enumerate the list to restore order lately; reduce the sorted list; restore orderdef append_unique(acc, item):return acc if key(acc[-1][1]) == key(item[1]) else acc.append(item) or accsrt_enum = sorted(enumerate(iterable), key=lambda item: key(item[1]))return [item[1] for item in sorted(reduce(append_unique, srt_enum, [srt_enum[0]]))]

它需要安装一个第三方模块,但包iteration_utilities包含一个#11函数,可以删除所有重复项,同时保留顺序:

>>> from iteration_utilities import unique_everseen
>>> list(unique_everseen(['a', 'b', 'c', 'd'] + ['a', 'c', 'd']))['a', 'b', 'c', 'd']

如果您想避免列表添加操作的开销,您可以使用#0代替:

>>> from itertools import chain>>> list(unique_everseen(chain(['a', 'b', 'c', 'd'], ['a', 'c', 'd'])))['a', 'b', 'c', 'd']

如果列表中有不可访问的项目(例如列表),则unique_everseen也有效:

>>> from iteration_utilities import unique_everseen>>> list(unique_everseen([['a'], ['b'], 'c', 'd'] + ['a', 'c', 'd']))[['a'], ['b'], 'c', 'd', 'a']

然而,这将是(多)慢于如果项目是散列。


1披露:我是iteration_utilities库的作者。

为了完整性,由于这是一个非常受欢迎的问题,Toolz库提供了#0函数:

>>> tuple(unique((1, 2, 3)))(1, 2, 3)>>> tuple(unique((1, 2, 1, 3)))(1, 2, 3)

这是最快的pythonic解决方案,可用于回复中列出的其他解决方案。

使用短路计算的实现细节允许使用列表理解,这是足够快的。visited.add(item)总是返回None作为结果,它被评估为False,所以or的右侧总是这样一个表达式的结果。

你自己计时

def deduplicate(sequence):visited = set()adder = visited.add  # get rid of qualification overheadout = [adder(item) or item for item in sequence if item not in visited]return out

你也可以这样做:

>>> t = [1, 2, 3, 3, 2, 4, 5, 6]>>> s = [x for i, x in enumerate(t) if i == t.index(x)]>>> s[1, 2, 3, 4, 5, 6]

上面有效的原因是index方法仅返回元素的第一个索引。重复的元素具有更高的索引。参考这里

list.index(x[, start[, end]])
在列表中返回从零开始的索引值为x的第一个项目。如果没有,则引发ValueError这样的项目。

我认为转换为set是删除重复的最简单方法:

list1 = [1,2,1]list1 = list(set(list1))print list1

使用set

a = [0,1,2,3,4,3,3,4]a = list(set(a))print a

使用独一无二的

import numpy as npa = [0,1,2,3,4,3,3,4]a = np.unique(a).tolist()print a

从列表中删除重复项的最佳方法是使用set()函数,在python中可用,再次转换列入列表

In [2]: some_list = ['a','a','v','v','v','c','c','d']In [3]: list(set(some_list))Out[3]: ['a', 'c', 'd', 'v']

您可以简单地通过使用集合来做到这一点。

step1:获取列表的不同元素
step2获取列表的公共元素
Step3合并它们

In [1]: a = ["apples", "bananas", "cucumbers"]
In [2]: b = ["pears", "apples", "watermelons"]
In [3]: set(a).symmetric_difference(b).union(set(a).intersection(b))Out[3]: {'apples', 'bananas', 'cucumbers', 'pears', 'watermelons'}
def remove_duplicates(A):[A.pop(count) for count,elem in enumerate(A) if A.count(elem)!=1]return A

删除重复项的列表压缩

如果你不关心顺序,想要一些不同于上面建议的pythonic方式的东西(也就是说,它可以在面试中使用),那么:

def remove_dup(arr):size = len(arr)j = 0    # To store index of next unique elementfor i in range(0, size-1):# If current element is not equal# to next element then store that# current elementif(arr[i] != arr[i+1]):arr[j] = arr[i]j+=1
arr[j] = arr[size-1] # Store the last element as whether it is unique or repeated, it hasn't stored previously
return arr[0:j+1]
if __name__ == '__main__':arr = [10, 10, 1, 1, 1, 3, 3, 4, 5, 6, 7, 8, 8, 9]print(remove_dup(sorted(arr)))

时间复杂度:O(n)

辅助空间:O(n)

参考:http://www.geeksforgeeks.org/remove-duplicates-sorted-array/

不使用set

data=[1, 2, 3, 1, 2, 5, 6, 7, 8]uni_data=[]for dat in data:if dat not in uni_data:uni_data.append(dat)
print(uni_data)

这里有很多答案使用set(..)(如果元素是可散列,它会很快)或列表(它的缺点是它会导致O(n2算法。

我建议的函数是一个混合函数:我们对可散列的项目使用set(..),对不可散列的项目使用list(..)。此外,它被实现为发生器,这样我们就可以限制项目的数量,或者做一些额外的过滤。

最后,我们还可以使用key参数来指定元素的唯一方式。例如,如果我们想过滤字符串列表,以便输出中的每个字符串都有不同的长度,我们可以使用它。

def uniq(iterable, key=lambda x: x):seens = set()seenl = []for item in iterable:k = key(item)try:seen = k in seensexcept TypeError:seen = k in seenlif not seen:yield itemtry:seens.add(k)except TypeError:seenl.append(k)

例如,我们现在可以像这样使用:

>>> list(uniq(["apple", "pear", "banana", "lemon"], len))['apple', 'pear', 'banana']>>> list(uniq(["apple", "pear", "lemon", "banana"], len))['apple', 'pear', 'banana']>>> list(uniq(["apple", "pear", {}, "lemon", [], "banana"], len))['apple', 'pear', {}, 'banana']>>> list(uniq(["apple", "pear", {}, "lemon", [], "banana"]))['apple', 'pear', {}, 'lemon', [], 'banana']>>> list(uniq(["apple", "pear", {}, "lemon", {}, "banana"]))['apple', 'pear', {}, 'lemon', 'banana']

因此,它是一个唯一性过滤器,可以处理任何可迭代的并过滤掉唯一性,无论这些唯一性是否可散列。

它做了一个假设:如果一个对象是可散列的,而另一个对象不是,那么两个对象永远不会相等。严格来说,这可能会发生,尽管这很少见。

另一种解决方案可能如下:从列表中创建一个字典,以项目为键,索引为值,然后打印字典键。

>>> lst = [1, 3, 4, 2, 1, 21, 1, 32, 21, 1, 6, 5, 7, 8, 2]>>>>>> dict_enum = {item:index for index, item in enumerate(lst)}>>> print dict_enum.keys()[32, 1, 2, 3, 4, 5, 6, 7, 8, 21]
def remove_duplicates(input_list):if input_list == []:return []#sort list from smallest to largestinput_list=sorted(input_list)#initialize ouput list with first element of the       sorted input listoutput_list = [input_list[0]]for item in input_list:if item >output_list[-1]:output_list.append(item)return output_list

在Python 3中非常简单的方法:

>>> n = [1, 2, 3, 4, 1, 1]>>> n[1, 2, 3, 4, 1, 1]>>> m = sorted(list(set(n)))>>> m[1, 2, 3, 4]
list_with_unique_items = list(set(list_with_duplicates))

不幸的是,这里的大多数答案要么没有保持顺序,要么太长。这是一个简单的,保持顺序的答案。

s = [1,2,3,4,5,2,5,6,7,1,3,9,3,5]x=[]
[x.append(i) for i in s if i not in x]print(x)

这将为您提供x,删除重复项但保留顺序。

这只是一个可读性的函数,很容易理解,我使用了字典数据结构,我使用了一些内置函数和更好的复杂度O(n)

def undup(dup_list):b={}for i in dup_list:b.update({i:1})return b.keys()a=["a",'b','a']print undup(a)

disclier:u可能会收到缩进错误(如果复制和粘贴),请在粘贴之前使用上面的代码并进行适当的缩进

您可以使用set删除重复项:

mylist = list(set(mylist))

但请注意,结果将是无序的。如果这是一个问题:

mylist.sort()

一个更好的方法是,

import pandas as pd
myList = [1, 2, 3, 1, 2, 5, 6, 7, 8]cleanList = pd.Series(myList).drop_duplicates().tolist()print(cleanList)
#> [1, 2, 3, 5, 6, 7, 8]

秩序仍然保留。

Python内置了许多函数,您可以使用set()来删除列表中的重复项。根据你的例子,下面有两个列表t和t2

t = ['a', 'b', 'c', 'd']t2 = ['a', 'c', 'd']result = list(set(t) - set(t2))result

答案:['b']

您可以使用以下功能:

def rem_dupes(dup_list):yooneeks = []for elem in dup_list:if elem not in yooneeks:yooneeks.append(elem)return yooneeks

示例

my_list = ['this','is','a','list','with','dupicates','in', 'the', 'list']

用法:

rem_dupes(my_list)

['this','is','a','list','with','dupicates','in','the']

有时您需要在不创建新列表的情况下删除重复的项目。例如,列表很大,或者将其保留为影子副本

from collections import CountercntDict = Counter(t)for item,cnt in cntDict.items():for _ in range(cnt-1):t.remove(item)

如果你想保持顺序,而不使用任何外部模块,这里有一个简单的方法来做到这一点:

>>> t = [1, 9, 2, 3, 4, 5, 3, 6, 7, 5, 8, 9]>>> list(dict.fromkeys(t))[1, 9, 2, 3, 4, 5, 6, 7, 8]

注意:此方法保留了出现的顺序,因此,如上所述,9将在1之后出现,因为它是第一次出现

from collections import OrderedDictulist=list(OrderedDict.fromkeys(l))

但它更短,跑得更快。

这是有效的,因为每次fromkeys函数尝试创建一个新键时,如果该值已经存在,它将简单地覆盖它。然而,这根本不会影响字典,因为fromkeys创建了一个字典,其中所有键的值都为None,所以有效地消除了所有重复。

如果您的列表是有序的,您可以使用以下方法遍历它,跳过重复的值。这对于处理内存消耗低的大列表特别有用,避免构建dictset的成本:

def uniq(iterator):prev = Nonefor item in iterator:if item != prev:prev = itemyield item

然后:

for item in uniq([1, 1, 3, 5, 5, 6]):print(item, end=' ')

输出将是:1 3 5 6

要返回列表对象,您可以执行以下操作:

>>> print(list(uniq([1, 1, 3, 5, 5, 6])))[1, 3, 5, 6]

Python内置类型的魔力

在python中,处理这样的复杂情况非常容易,并且只能通过python的内置类型。

让我告诉你怎么做!

方法一:一般案例

删除列表中重复元素并保持排序顺序的方法(1行代码

line = [1, 2, 3, 1, 2, 5, 6, 7, 8]new_line = sorted(set(line), key=line.index) # remove duplicated elementprint(new_line)

你会得到结果的

[1, 2, 3, 5, 6, 7, 8]

方法二:特殊情况

TypeError: unhashable type: 'list'

处理不可访问的特殊情况(3行代码

line=[['16.4966155686595', '-27.59776154691', '52.3786295521147'],['16.4966155686595', '-27.59776154691', '52.3786295521147'],['17.6508629295574', '-27.143305738671', '47.534955022564'],['17.6508629295574', '-27.143305738671', '47.534955022564'],['18.8051102904552', '-26.688849930432', '42.6912804930134'],['18.8051102904552', '-26.688849930432', '42.6912804930134'],['19.5504702331098', '-26.205884452727', '37.7709192714727'],['19.5504702331098', '-26.205884452727', '37.7709192714727'],['20.2929416861422', '-25.722717575124', '32.8500163147157'],['20.2929416861422', '-25.722717575124', '32.8500163147157']]
tuple_line = [tuple(pt) for pt in line] # convert list of list into list of tupletuple_new_line = sorted(set(tuple_line),key=tuple_line.index) # remove duplicated elementnew_line = [list(t) for t in tuple_new_line] # convert list of tuple into list of list
print (new_line)

你会得到结果:

[['16.4966155686595', '-27.59776154691', '52.3786295521147'],['17.6508629295574', '-27.143305738671', '47.534955022564'],['18.8051102904552', '-26.688849930432', '42.6912804930134'],['19.5504702331098', '-26.205884452727', '37.7709192714727'],['20.2929416861422', '-25.722717575124', '32.8500163147157']]

因为元组是可散列的,您可以轻松地在列表和元组之间转换数据

在这个答案中,将有两个部分:两个独特的解决方案,以及特定解决方案的速度图。

删除重复项

这些答案中的大多数只删除了可散列的重复项,但这个问题并不意味着它不仅仅需要可散列项,这意味着我将提供一些不需要可散列项的解决方案。

collections.Counter是标准库中的一个强大工具,可以完美地实现这一点。只有一个其他解决方案甚至包含计数器。然而,该解决方案也仅限于可散列键。

为了允许计数器中的不可哈希键,我创建了一个Container类,它将尝试获取对象的默认哈希函数,但如果失败,它将尝试其身份函数。它还定义了一个eq和一个哈希方法。这应该足以在我们的解决方案中允许无法项。不可哈希对象将被视为可哈希。然而,这个哈希函数对不可哈希对象使用身份,这意味着两个相等的对象都是不可哈希的将不起作用。我建议你覆盖它,并将其更改为使用等效可变类型的哈希(例如,如果my_list是列表,则使用hash(tuple(my_list)))。

我还做了两个解决方案。另一个解决方案保持项目的顺序,使用OrderedDictOrderedCounter的子类,名为'OrderedCounter'。现在,这是函数:

from collections import OrderedDict, Counter
class Container:def __init__(self, obj):self.obj = objdef __eq__(self, obj):return self.obj == objdef __hash__(self):try:return hash(self.obj)except:return id(self.obj)
class OrderedCounter(Counter, OrderedDict):'Counter that remembers the order elements are first encountered'
def __repr__(self):return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):return self.__class__, (OrderedDict(self),)    
def remd(sequence):cnt = Counter()for x in sequence:cnt[Container(x)] += 1return [item.obj for item in cnt]
def oremd(sequence):cnt = OrderedCounter()for x in sequence:cnt[Container(x)] += 1return [item.obj for item in cnt]

remd是非有序排序,而oremd是有序排序。你可以清楚地分辨出哪一个更快,但无论如何我会解释。非有序排序稍微快一点,因为它不存储项目的顺序。

现在,我还想展示每个答案的速度比较。所以,我现在就做。

哪个功能最快?

为了消除重复,我从几个答案中收集了10个函数。我计算了每个函数的速度,并使用matplotlib.pyplot将其放入图表中。

我将其分为三轮图形。哈希可是任何可以哈希的对象,不可哈希是任何不能哈希的对象。有序序列是保持秩序的序列,无序序列不保持秩序。现在,这里还有一些术语:

无序可拆分适用于删除重复项的任何方法,这些方法不一定要保持顺序。它不一定适用于不可解的对象,但它可以。

已排序适用于保持列表中项目顺序的任何方法,但它不必适用于不可处理的对象,但它可以。

已下单是保持列表中项目顺序的任何方法,并且适用于不可更改的对象。

在y轴上是它所花费的秒数。

在x轴上是函数应用到的数字。

我为无序散列和有序散列生成了序列,理解如下:[list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]

对于有序的unashable:[[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]

请注意,范围中有一个step,因为没有它,这将花费10倍的时间。也因为在我个人看来,我认为它可能看起来更容易阅读。

还要注意图例上的键是我试图猜测的函数实现的最重要部分。至于什么函数做得最差或最好?图表不言自明。

解决了这个问题,这里是图表。

无序哈斯哈布

无序哈希布(放大)无序可缩放

已订购Hashable

已排序的哈斯哈布(放大)已缩放的已排序哈斯哈布

订购Unhashable

已排序的不可处理(放大)已缩放的已排序不可处理对象

很晚才回答
如果您不关心列表顺序,您可以使用*arg扩展和set唯一性来删除重复,即:

l = [*{*l}]

Python3演示

我用纯python函数做到了这一点。当你的items值是JSON时,这是有效的。

[i for n, i in enumerate(items) if i not in items[n + 1 :]]

我没有看到不可哈希值的答案,一个班轮,n log n,仅限标准库,所以这是我的答案:

list(map(operator.itemgetter(0), itertools.groupby(sorted(items))))

或者作为生成器函数:

def unique(items: Iterable[T]) -> Iterable[T]:"""For unhashable items (can't use set to unique) with a partial order"""yield from map(operator.itemgetter(0), itertools.groupby(sorted(items)))
Test = [1,8,2,7,3,4,5,1,2,3,6]Test.sort()i=1while i< len(Test):if Test[i] == Test[i-1]:Test.remove(Test[i])i= i+1print(Test)

检查字符串'a'和'b'

clean_list = []for ele in raw_list:if 'b' in ele or 'a' in ele:passelse:clean_list.append(ele)
Write a Python program to create a list of numbers by taking input from the user and then remove  the duplicates from the list. You can take input of non-zero numbers, with an appropriate  prompt, from the user until the user enters a zero to create the list assuming that the numbers  are non-zero.Sample Input: [10, 34, 18, 10, 12, 34, 18, 20, 25, 20]Output: [10, 34, 18, 12, 20, 25]
lst = []print("ENTER ZERO NUMBER FOR EXIT !!!!!!!!!!!!")print("ENTER LIST ELEMENTS  :: ")while True:n = int(input())if n == 0 :print("!!!!!!!!!!! EXIT !!!!!!!!!!!!")breakelse :lst.append(n)print("LIST ELEMENR ARE :: ",lst)#dup = set()uniq = []for x in lst:if x not in uniq:uniq.append(x)# dup.add(x)print("UNIQUE ELEMENTS IN LIST ARE :: ",uniq)
  • 您可以使用Python设置或dict.fromkeys()方法删除重复

  • dict.fromkeys()方法转换 a列表到字典.字典不能包含重复值,因此只有唯一值的字典由dict.fromkeys()返回。

  • 设置和字典一样,不能包含重复值。如果我们转换一个列表到一组,所有的重复被删除

方法1:朴素方法
mylist = [5, 10, 15, 20, 3, 15, 25, 20, 30, 10, 100]
uniques = []
for i in mylist:
if i not in uniques:
uniques.append(i)
print(uniques)
方法2:使用set()
mylist = [5, 10, 15, 20, 3, 15, 25, 20, 30, 10, 100]
myset = set(mylist)
print(list(myset))

我已经将各种建议与灌流图进行了比较。事实证明,如果输入数组没有重复元素,所有方法或多或少都一样快,与输入数据是Python列表还是NumPy数组无关。

在此处输入图片描述

如果输入数组很大,但只包含一个唯一元素,那么setdictnp.unique方法是成本时间如果输入数据是列表。如果它是一个NumPy数组,np.unique比其他替代方案快大约10倍。

在此处输入图片描述

让我有点惊讶的是,这些操作也不是恒定时间操作。


重现情节的代码:

import perfplotimport numpy as npimport matplotlib.pyplot as plt

def setup_list(n):# return list(np.random.permutation(np.arange(n)))return [0] * n

def setup_np_array(n):# return np.random.permutation(np.arange(n))return np.zeros(n, dtype=int)

def list_set(data):return list(set(data))

def numpy_unique(data):return np.unique(data)

def list_dict(data):return list(dict.fromkeys(data))

b = perfplot.bench(setup=[setup_list,setup_list,setup_list,setup_np_array,setup_np_array,setup_np_array,],kernels=[list_set, numpy_unique, list_dict, list_set, numpy_unique, list_dict],labels=["list(set(lst))","np.unique(lst)","list(dict(lst))","list(set(arr))","np.unique(arr)","list(dict(arr))",],n_range=[2 ** k for k in range(23)],xlabel="len(array)",equality_check=None,)# plt.title("input array = [0, 1, 2,..., n]")plt.title("input array = [0, 0,..., 0]")b.save("out.png")b.show()

使用集合,但保持顺序

unique = set()[unique.add(n) or n for n in l if n not in unique]

您可以比较集合和列表的长度,并将集合项保存到列表中。

if len(t) != len(set(t)):t = [x for x in set(t)]     
mylist = ["a", "b", "a", "c", "c"]mylist = list(dict.fromkeys(mylist))print(mylist)