जवाबों:
का प्रयोग करें set()
डुप्लिकेट को निकालने के यदि सभी मूल्यों हैं hashable :
>>> your_list = ['one', 'two', 'one']
>>> len(your_list) != len(set(your_list))
True
केवल छोटी सूचियों के लिए अनुशंसित :
any(thelist.count(x) > 1 for x in thelist)
है न एक लंबी सूची पर उपयोग - यह करने के लिए समय आनुपातिक ले जा सकते हैं वर्ग सूची में आइटम्स की संख्या के!
लंबी वस्तुओं के साथ लंबी सूची के लिए (तार, संख्या और ग):
def anydup(thelist):
seen = set()
for x in thelist:
if x in seen: return True
seen.add(x)
return False
यदि आपकी वस्तुएं उपलब्ध नहीं हैं (सब्लिस्ट, डाइक, इत्यादि) तो यह बालों के रंग के हो जाते हैं, हालांकि यदि उन्हें कम से कम तुलनीय हो तो भी O (N logN) प्राप्त करना संभव हो सकता है। लेकिन आपको सबसे अच्छी परफॉरमेंस पाने के लिए आइटम्स (हैज़ेबल या नहीं, तुलनीय या नहीं) की विशेषताओं को जानना या परखना होगा - हैशेल्स के लिए O (N), नॉन-हैज़ेबल तुलना के लिए O (N लॉग एन), अन्यथा यह O (N वर्ग) के नीचे है और इसके बारे में कोई भी कुछ नहीं कर सकता है :-(
all
सभी 1 पर गिना जाता है) की आवश्यकता है। सभी मूल्यों के साथ एक तानाशाह, जिसका आप भी उल्लेख करते हैं, एक हास्यास्पद है, बेकार फूला हुआ नकल है set
, जिसका कोई जोड़ मूल्य नहीं है। बिग-ओ प्रोग्रामिंग में सब कुछ नहीं है।
यह पुराना है, लेकिन यहां के जवाबों ने मुझे थोड़ा अलग समाधान दिया। यदि आप गालियां देने के लिए तैयार हैं, तो आप इस तरह से कम-चक्कर लगा सकते हैं।
xs = [1, 2, 1]
s = set()
any(x in s or s.add(x) for x in xs)
# You can use a similar approach to actually retrieve the duplicates.
s = set()
duplicates = set(x for x in xs if x in s or s.add(x))
आप कार्यात्मक प्रोग्रामिंग शैली के शौकीन हैं, तो यहां एक उपयोगी समारोह, आत्म दस्तावेज और का उपयोग कर कोड का परीक्षण किया है doctest ।
def decompose(a_list):
"""Turns a list into a set of all elements and a set of duplicated elements.
Returns a pair of sets. The first one contains elements
that are found at least once in the list. The second one
contains elements that appear more than once.
>>> decompose([1,2,3,5,3,2,6])
(set([1, 2, 3, 5, 6]), set([2, 3]))
"""
return reduce(
lambda (u, d), o : (u.union([o]), d.union(u.intersection([o]))),
a_list,
(set(), set()))
if __name__ == "__main__":
import doctest
doctest.testmod()
वहां से आप यह जाँच कर एकता का परीक्षण कर सकते हैं कि क्या लौटे हुए जोड़े का दूसरा तत्व खाली है:
def is_set(l):
"""Test if there is no duplicate element in l.
>>> is_set([1,2,3])
True
>>> is_set([1,2,1])
False
>>> is_set([])
True
"""
return not decompose(l)[1]
ध्यान दें कि यह कुशल नहीं है क्योंकि आप स्पष्ट रूप से अपघटन का निर्माण कर रहे हैं। लेकिन कम उपयोग करने की रेखा के साथ, आप 5 के उत्तर के लिए कुछ समतुल्य (लेकिन थोड़ा कम कुशल) तक आ सकते हैं:
def is_set(l):
try:
def func(s, o):
if o in s:
raise Exception
return s.union([o])
reduce(func, l, set())
return True
except:
return False
मुझे लगा कि यहां प्रस्तुत विभिन्न समाधानों के समय की तुलना करना उपयोगी होगा। इसके लिए मैंने अपनी लाइब्रेरी का उपयोग किया simple_benchmark
:
तो वास्तव में इस मामले के लिए डेनिस ओटकिडैच से समाधान सबसे तेज़ है।
कुछ दृष्टिकोण भी बहुत स्टेटर वक्र को प्रदर्शित करते हैं, ये ऐसे तत्व हैं जो तत्वों की संख्या के साथ द्विघात पैमाने पर हैं (एलेक्स मार्टेलिस पहला समाधान, वेजेंड्रिया और दोनों जेवियर डेकोरेट समाधान)। यह भी उल्लेख करना महत्वपूर्ण है कि कीकू के पांडा समाधान में एक बहुत बड़ा स्थिर कारक है। लेकिन बड़ी सूचियों के लिए यह अन्य समाधानों के साथ लगभग पकड़ लेता है।
और मामले में डुप्लिकेट पहले स्थान पर है। यह देखने के लिए उपयोगी है कि कौन से समाधान छोटे-चक्कर वाले हैं:
यहां कई दृष्टिकोण शॉर्ट-सर्किट नहीं हैं: कैकु, फ्रैंक, ज़ेवियर_डेकोरेट (पहला समाधान), टर्न, एलेक्स मार्टेली (पहला समाधान) और डेनिस ओटकिडैच द्वारा प्रस्तुत दृष्टिकोण (जो कि डुप्लिकेट मामले में सबसे तेज़ था)।
मैंने यहां अपने स्वयं के पुस्तकालय से एक समारोह को शामिल किया: iteration_utilities.all_distinct
जो कि डुप्लिकेट-एट-स्टार्ट मामले के लिए निरंतर-समय में सबसे तेजी से समाधान के साथ प्रतिस्पर्धा कर सकता है और निरंतर समय में प्रदर्शन करता है (हालांकि सबसे तेज नहीं)।
बेंचमार्क के लिए कोड:
from collections import Counter
from functools import reduce
import pandas as pd
from simple_benchmark import BenchmarkBuilder
from iteration_utilities import all_distinct
b = BenchmarkBuilder()
@b.add_function()
def Keiku(l):
return pd.Series(l).duplicated().sum() > 0
@b.add_function()
def Frank(num_list):
unique = []
dupes = []
for i in num_list:
if i not in unique:
unique.append(i)
else:
dupes.append(i)
if len(dupes) != 0:
return False
else:
return True
@b.add_function()
def wjandrea(iterable):
seen = []
for x in iterable:
if x in seen:
return True
seen.append(x)
return False
@b.add_function()
def user(iterable):
clean_elements_set = set()
clean_elements_set_add = clean_elements_set.add
for possible_duplicate_element in iterable:
if possible_duplicate_element in clean_elements_set:
return True
else:
clean_elements_set_add( possible_duplicate_element )
return False
@b.add_function()
def Turn(l):
return Counter(l).most_common()[0][1] > 1
def getDupes(l):
seen = set()
seen_add = seen.add
for x in l:
if x in seen or seen_add(x):
yield x
@b.add_function()
def F1Rumors(l):
try:
if next(getDupes(l)): return True # Found a dupe
except StopIteration:
pass
return False
def decompose(a_list):
return reduce(
lambda u, o : (u[0].union([o]), u[1].union(u[0].intersection([o]))),
a_list,
(set(), set()))
@b.add_function()
def Xavier_Decoret_1(l):
return not decompose(l)[1]
@b.add_function()
def Xavier_Decoret_2(l):
try:
def func(s, o):
if o in s:
raise Exception
return s.union([o])
reduce(func, l, set())
return True
except:
return False
@b.add_function()
def pyrospade(xs):
s = set()
return any(x in s or s.add(x) for x in xs)
@b.add_function()
def Alex_Martelli_1(thelist):
return any(thelist.count(x) > 1 for x in thelist)
@b.add_function()
def Alex_Martelli_2(thelist):
seen = set()
for x in thelist:
if x in seen: return True
seen.add(x)
return False
@b.add_function()
def Denis_Otkidach(your_list):
return len(your_list) != len(set(your_list))
@b.add_function()
def MSeifert04(l):
return not all_distinct(l)
और तर्क के लिए:
# No duplicate run
@b.add_arguments('list size')
def arguments():
for exp in range(2, 14):
size = 2**exp
yield size, list(range(size))
# Duplicate at beginning run
@b.add_arguments('list size')
def arguments():
for exp in range(2, 14):
size = 2**exp
yield size, [0, *list(range(size)]
# Running and plotting
r = b.run()
r.plot()
मैंने हाल ही में एक जनरेटर का उपयोग करके, एक सूची में सभी डुप्लिकेट स्थापित करने के लिए संबंधित प्रश्न का उत्तर दिया । इसका यह फायदा है कि अगर सिर्फ 'अगर कोई डुप्लिकेट है' स्थापित करने के लिए उपयोग किया जाता है, तो आपको केवल पहली वस्तु प्राप्त करने की आवश्यकता है और बाकी को अनदेखा किया जा सकता है, जो कि अंतिम शॉर्टकट है।
यह एक दिलचस्प सेट आधारित दृष्टिकोण है जिसे मैंने सीधे मूओइप से अनुकूलित किया है :
def getDupes(l):
seen = set()
seen_add = seen.add
for x in l:
if x in seen or seen_add(x):
yield x
तदनुसार, द्वैध की पूरी सूची होगी list(getDupes(etc))
। केवल "यदि" एक डुबकी है, तो इसका परीक्षण करने के लिए, इसे निम्न प्रकार से लपेटा जाना चाहिए:
def hasDupes(l):
try:
if getDupes(l).next(): return True # Found a dupe
except StopIteration:
pass
return False
यह अच्छी तरह से तराजू और लगातार ऑपरेटिंग समय प्रदान करता है जहां भी डुप सूची में है - मैंने 1 मी प्रविष्टियों तक की सूचियों के साथ परीक्षण किया। यदि आप डेटा के बारे में कुछ जानते हैं, विशेष रूप से, यह कि पहली छमाही में डूप दिखाने की संभावना है, या अन्य चीजें जो आपको अपनी आवश्यकताओं को तिरछा करने देती हैं, जैसे कि वास्तविक डुप्स प्राप्त करने की आवश्यकता होती है, तो वास्तव में वैकल्पिक ड्यूप लोकेटर के एक जोड़े हैं यह बेहतर हो सकता है। मैं दो की सिफारिश कर रहे हैं ...
सरल तानाशाही आधारित दृष्टिकोण, बहुत पठनीय:
def getDupes(c):
d = {}
for i in c:
if i in d:
if d[i]:
yield i
d[i] = False
else:
d[i] = True
सॉर्ट की गई सूची पर उत्तोलन इटर्टूल (अनिवार्य रूप से एक इफिल्टर / izip / टी), बहुत ही कुशल यदि आप सभी डुप्लिकेट प्राप्त कर रहे हैं, हालांकि केवल पहले प्राप्त करने के लिए जल्दी नहीं।
def getDupes(c):
a, b = itertools.tee(sorted(c))
next(b, None)
r = None
for k, g in itertools.ifilter(lambda x: x[0]==x[1], itertools.izip(a, b)):
if k != r:
yield k
r = k
मैं पूर्ण द्वैध सूची के लिए जिन तरीकों की कोशिश कर रहा था, उनमें से ये शीर्ष कलाकार थे , पहली बार में कहीं भी 1 मी तत्व सूची में शुरुआत से लेकर मध्य तक होने वाली पहली थाप के साथ। यह आश्चर्य की बात है कि कैसे छोटे कदम की तरह जोड़ा गया था। आपका लाभ भिन्न हो सकता है, लेकिन यहां मेरे विशिष्ट समय परिणाम हैं:
Finding FIRST duplicate, single dupe places "n" elements in to 1m element array
Test set len change : 50 - . . . . . -- 0.002
Test in dict : 50 - . . . . . -- 0.002
Test in set : 50 - . . . . . -- 0.002
Test sort/adjacent : 50 - . . . . . -- 0.023
Test sort/groupby : 50 - . . . . . -- 0.026
Test sort/zip : 50 - . . . . . -- 1.102
Test sort/izip : 50 - . . . . . -- 0.035
Test sort/tee/izip : 50 - . . . . . -- 0.024
Test moooeeeep : 50 - . . . . . -- 0.001 *
Test iter*/sorted : 50 - . . . . . -- 0.027
Test set len change : 5000 - . . . . . -- 0.017
Test in dict : 5000 - . . . . . -- 0.003 *
Test in set : 5000 - . . . . . -- 0.004
Test sort/adjacent : 5000 - . . . . . -- 0.031
Test sort/groupby : 5000 - . . . . . -- 0.035
Test sort/zip : 5000 - . . . . . -- 1.080
Test sort/izip : 5000 - . . . . . -- 0.043
Test sort/tee/izip : 5000 - . . . . . -- 0.031
Test moooeeeep : 5000 - . . . . . -- 0.003 *
Test iter*/sorted : 5000 - . . . . . -- 0.031
Test set len change : 50000 - . . . . . -- 0.035
Test in dict : 50000 - . . . . . -- 0.023
Test in set : 50000 - . . . . . -- 0.023
Test sort/adjacent : 50000 - . . . . . -- 0.036
Test sort/groupby : 50000 - . . . . . -- 0.134
Test sort/zip : 50000 - . . . . . -- 1.121
Test sort/izip : 50000 - . . . . . -- 0.054
Test sort/tee/izip : 50000 - . . . . . -- 0.045
Test moooeeeep : 50000 - . . . . . -- 0.019 *
Test iter*/sorted : 50000 - . . . . . -- 0.055
Test set len change : 500000 - . . . . . -- 0.249
Test in dict : 500000 - . . . . . -- 0.145
Test in set : 500000 - . . . . . -- 0.165
Test sort/adjacent : 500000 - . . . . . -- 0.139
Test sort/groupby : 500000 - . . . . . -- 1.138
Test sort/zip : 500000 - . . . . . -- 1.159
Test sort/izip : 500000 - . . . . . -- 0.126
Test sort/tee/izip : 500000 - . . . . . -- 0.120 *
Test moooeeeep : 500000 - . . . . . -- 0.131
Test iter*/sorted : 500000 - . . . . . -- 0.157
.next()
अपने दूसरे कोड ब्लॉक में कॉल अजगर 3.x. पर काम नहीं करता मुझे लगता है कि next(getDupes(l))
पायथन संस्करणों में काम करना चाहिए, इसलिए इसे बदलने के लिए समझ में आ सकता है।
ifilter
और ìzip
बस में निर्मित द्वारा बदला जा सकता है filter
और zip
अजगर 3.x. में
इस तरह से करने का एक और तरीका काउंटर के साथ है ।
यह निर्धारित करने के लिए कि क्या मूल सूची में कोई डुप्लिकेट हैं:
from collections import Counter
def has_dupes(l):
# second element of the tuple has number of repetitions
return Counter(l).most_common()[0][1] > 1
या डुप्लिकेट वाले आइटम की सूची प्राप्त करने के लिए:
def get_dupes(l):
return [k for k, v in Counter(l).items() if v > 1]
मुझे यह सबसे अच्छा प्रदर्शन करने के लिए मिला क्योंकि यह शॉर्ट-सर्किट ऑपरेशन है जब पहली बार इसे डुप्लिकेट पाया गया, तो इस एल्गोरिथ्म में समय और स्थान जटिलता ओ (एन) है जहां n सूची की लंबाई है:
def has_duplicated_elements(iterable):
""" Given an `iterable`, return True if there are duplicated entries. """
clean_elements_set = set()
clean_elements_set_add = clean_elements_set.add
for possible_duplicate_element in iterable:
if possible_duplicate_element in clean_elements_set:
return True
else:
clean_elements_set_add( possible_duplicate_element )
return False
एक और अधिक सरल समाधान इस प्रकार है। बस पांडा .duplicated()
विधि के साथ सही / गलत की जाँच करें और फिर राशि लें। कृपया pandas.Series.duplicated - पांडा 0.24.1 प्रलेखन भी देखें
import pandas as pd
def has_duplicated(l):
return pd.Series(l).duplicated().sum() > 0
print(has_duplicated(['one', 'two', 'one']))
# True
print(has_duplicated(['one', 'two', 'three']))
# False
यदि सूची में उपलब्ध आइटम नहीं हैं, तो आप एलेक्स मार्टेली के समाधान का उपयोग कर सकते हैं लेकिन एक सेट के बजाय एक सूची के साथ, हालांकि यह बड़े इनपुट के लिए धीमा है: O (N ^ 2)।
def has_duplicates(iterable):
seen = []
for x in iterable:
if x in seen:
return True
seen.append(x)
return False
मैंने इसकी सरलता के लिए पायरोसेपडे के दृष्टिकोण का उपयोग किया, और केस-इन्सेंसेंस विंडोज रजिस्ट्री से बनाई गई एक छोटी सूची पर थोड़ा संशोधित किया।
यदि कच्चे पथ मूल्य स्ट्रिंग को अलग-अलग रास्तों में विभाजित किया जाता है, तो सभी 'शून्य' पथ (खाली या व्हाट्सएप-केवल स्ट्रिंग्स) का उपयोग करके हटाया जा सकता है:
PATH_nonulls = [s for s in PATH if s.strip()]
def HasDupes(aseq) :
s = set()
return any(((x.lower() in s) or s.add(x.lower())) for x in aseq)
def GetDupes(aseq) :
s = set()
return set(x for x in aseq if ((x.lower() in s) or s.add(x.lower())))
def DelDupes(aseq) :
seen = set()
return [x for x in aseq if (x.lower() not in seen) and (not seen.add(x.lower()))]
मूल PATH में परीक्षण प्रयोजनों के लिए 'null' प्रविष्टियाँ और डुप्लिकेट दोनों हैं:
[list] Root paths in HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment:PATH[list] Root paths in HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
1 C:\Python37\
2
3
4 C:\Python37\Scripts\
5 c:\python37\
6 C:\Program Files\ImageMagick-7.0.8-Q8
7 C:\Program Files (x86)\poppler\bin
8 D:\DATA\Sounds
9 C:\Program Files (x86)\GnuWin32\bin
10 C:\Program Files (x86)\Intel\iCLS Client\
11 C:\Program Files\Intel\iCLS Client\
12 D:\DATA\CCMD\FF
13 D:\DATA\CCMD
14 D:\DATA\UTIL
15 C:\
16 D:\DATA\UHELP
17 %SystemRoot%\system32
18
19
20 D:\DATA\CCMD\FF%SystemRoot%
21 D:\DATA\Sounds
22 %SystemRoot%\System32\Wbem
23 D:\DATA\CCMD\FF
24
25
26 c:\
27 %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\
28
अशक्त रास्ते हटा दिए गए हैं, लेकिन अभी भी डुप्लिकेट हैं, उदाहरण के लिए, (1, 3) और (13, 20):
[list] Null paths removed from HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment:PATH
1 C:\Python37\
2 C:\Python37\Scripts\
3 c:\python37\
4 C:\Program Files\ImageMagick-7.0.8-Q8
5 C:\Program Files (x86)\poppler\bin
6 D:\DATA\Sounds
7 C:\Program Files (x86)\GnuWin32\bin
8 C:\Program Files (x86)\Intel\iCLS Client\
9 C:\Program Files\Intel\iCLS Client\
10 D:\DATA\CCMD\FF
11 D:\DATA\CCMD
12 D:\DATA\UTIL
13 C:\
14 D:\DATA\UHELP
15 %SystemRoot%\system32
16 D:\DATA\CCMD\FF%SystemRoot%
17 D:\DATA\Sounds
18 %SystemRoot%\System32\Wbem
19 D:\DATA\CCMD\FF
20 c:\
21 %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\
और अंत में, डंप हटा दिए गए हैं:
[list] Massaged path list from in HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment:PATH
1 C:\Python37\
2 C:\Python37\Scripts\
3 C:\Program Files\ImageMagick-7.0.8-Q8
4 C:\Program Files (x86)\poppler\bin
5 D:\DATA\Sounds
6 C:\Program Files (x86)\GnuWin32\bin
7 C:\Program Files (x86)\Intel\iCLS Client\
8 C:\Program Files\Intel\iCLS Client\
9 D:\DATA\CCMD\FF
10 D:\DATA\CCMD
11 D:\DATA\UTIL
12 C:\
13 D:\DATA\UHELP
14 %SystemRoot%\system32
15 D:\DATA\CCMD\FF%SystemRoot%
16 %SystemRoot%\System32\Wbem
17 %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\
def check_duplicates(my_list):
seen = {}
for item in my_list:
if seen.get(item):
return True
seen[item] = True
return False