2015-02-23 52 views
1

我想要構建一個函數,如果列表中的任何兩個項目都相同,將返回True。列表中的重複

例如,[1,7,3,7,4]應返回True["one","ONE","One"]應返回False

我需要幫助python的哪些部分查找重複項。

+0

相關:[識別在Python列表重複值(http://stackoverflow.com/q/11236006 ) – 2015-02-23 16:27:55

回答

2

將值循環並使用set來跟蹤您已經看到的內容。只要你看到一個值再次,返回True

def has_duplicates(lst): 
    seen = set() 
    for elem in lst: 
     if elem in seen: 
      return True 
     seen.add(elem) 
    return False 

這是因爲它短路非常有效;如果早期檢測到重複,它將不會遍歷整個列表。

+0

列表不會更快嗎? ('seen = []')我做了一個快速的'timeit'('timeit.timeit(「s.add(5)」,「s = set()」)''爲'0.100 ...'和'timeit。 timeit(「s.append(5)」,「s = []」)'爲'0.0911') – 2015-02-23 16:30:30

+0

爲什麼不這樣做:'if len(set(lst))!= len(lst)' – RPGillespie 2015-02-23 16:30:31

+0

@RPGillespie因爲必須遍歷整個列表。 – 2015-02-23 16:31:03

1

Martijn的answer是最好的,但有一些例外,這是值得一試。

>>> chk = lambda x: len(l) != len(set(l)) # check the length after removing dupes. 
>>> l = [1,7,3,7,4] 
>>> chk(l) 
True 
>>> l = ["one","ONE","One"] 
>>> chk(l) 
False 

- 作爲Martijn提到了一個評論,這是一個緩慢的過程。

+1

這需要遍歷整個*列表。例如,用'[1] + list(range(1000000))'試試這個。 – 2015-02-23 16:28:30

+0

@MartijnPieters是的,這是一個非常緩慢的方式來做! :)(但希望不是*錯誤的方式) – 2015-02-23 16:29:40

1

使用collections.Counter字典:

from collections import Counter 
def has_dupes(l): 
    # if most repeated key count is > 1 we have at least one dupe 
    return Counter(l).most_common(1)[0][1] > 1 

或者使用any

def has_dupes(l): 
    return any(v > 1 for v in Counter(l).values()) 
+1

這比使用len(set(l))更慢,因爲它需要一個O(N)循環遍歷所有的值,然後創建一個堆來找到最常見的元素,再次O(N)。漸近地與len(set(l))相同,但每次迭代的固定成本較高。 – 2015-02-23 16:52:03

+1

@MartijnPieters,是的,但是一個線性的解決方案,另一個如何做OP的想法和一個Counter dict的介紹,這是一個非常有用的工具。如果問題是什麼是最佳的方式,因爲我有大量的數據,那麼這將是不同的,但事實並非如此。 – 2015-02-23 16:54:36

+1

我只是在評論解決方案的性能方面,因爲我認爲這很重要。否則,這整個問題只會是[在Python中的列表中識別重複值](http://stackoverflow.com/q/11236006) – 2015-02-23 16:57:32