[英]Python: Remove all duplicates from a large list of lists efficiently and elegantly
[英]Efficiently remove duplicates, order-agnostic, from list of lists
下面的列表有一些重復的子列表,元素的順序不同:
l1 = [
['The', 'quick', 'brown', 'fox'],
['hi', 'there'],
['jumps', 'over', 'the', 'lazy', 'dog'],
['there', 'hi'],
['jumps', 'dog', 'over','lazy', 'the'],
]
如何刪除重復項,保留看到的第一個實例,以獲得:
l1 = [
['The', 'quick', 'brown', 'fox'],
['hi', 'there'],
['jumps', 'over', 'the', 'lazy', 'dog'],
]
我試過了:
[list(i) for i in set(map(tuple, l1))]
盡管如此,我不知道這是否是大型列表的最快方法,而且我的嘗試沒有按預期工作。 知道如何有效地刪除它們嗎?
這個有點棘手。 您想從凍結的計數器中鍵入一個 dict,但計數器在 Python 中不可散列。 對於漸近復雜性的小幅下降,您可以使用排序元組作為凍結計數器的替代品:
seen = set()
result = []
for x in l1:
key = tuple(sorted(x))
if key not in seen:
result.append(x)
seen.add(key)
單行中的相同想法如下所示:
[*{tuple(sorted(k)): k for k in reversed(l1)}.values()][::-1]
我做了一個快速基准測試,比較了各種答案:
l1 = [['The', 'quick', 'brown', 'fox'], ['hi', 'there'], ['jumps', 'over', 'the', 'lazy', 'dog'], ['there', 'hi'], ['jumps', 'dog', 'over','lazy', 'the']]
from collections import Counter
def method1():
"""manually construct set, keyed on sorted tuple"""
seen = set()
result = []
for x in l1:
key = tuple(sorted(x))
if key not in seen:
result.append(x)
seen.add(key)
return result
def method2():
"""frozenset-of-Counter"""
return list({frozenset(Counter(lst).items()): lst for lst in reversed(l1)}.values())
def method3():
"""wim"""
return [*{tuple(sorted(k)): k for k in reversed(l1)}.values()][::-1]
from timeit import timeit
print(timeit(lambda: method1(), number=1000))
print(timeit(lambda: method2(), number=1000))
print(timeit(lambda: method3(), number=1000))
印刷:
0.0025010189856402576
0.016385524009820074
0.0026451340527273715
@wim 的答案效率低下,因為它將列表項排序為唯一標識一組列表項計數的一種方式,每個子列表的時間復雜度為O(n log n) 。
為了以線性時間復雜度實現相同的效果,您可以使用帶有collections.Counter
類的項目計數的凍結collections.Counter
。 由於 dict comprehension 保留了帶有重復鍵的項目的最后一個值,並且由於您希望在問題中保留帶有重復鍵的項目的第一個值,因此您必須以列表的相反順序構造 dict,然后再將其反轉已構建去重子列表列表:
from collections import Counter
list({frozenset(Counter(lst).items()): lst for lst in reversed(l1)}.values())[::-1]
這將返回:
[['The', 'quick', 'brown', 'fox'], ['hi', 'there'], ['jumps', 'over', 'the', 'lazy', 'dog']]
這個:
l1 = [['The', 'quick', 'brown', 'fox'], ['hi', 'there'], ['jumps', 'over', 'the', 'lazy', 'dog'], ['there', 'hi'], ['jumps', 'dog', 'over','lazy', 'the']]
s = {tuple(item) for item in map(sorted, l1)}
l2 = [list(item) for item in s]
l2 給出刪除了反向重復項的列表。 比較: 刪除列表中反向重復項的 Pythonic 方式
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.