bool(set(a) & set(b))
: पहला विकल्प सेट करने के लिए दोनों को बदलने और उनके चौराहे जाँच करने के लिए इस तरह के रूप है पायथन में ऑपरेटर)। सैद्धांतिक रूप से, n
और m
सूचियों में a
और b
में O(n+m)
औसत पर O(n+m)
है। लेकिन 1) इसे पहले सूचियों से सेट सेट करना होगा, जो एक गैर-नगण्य समय ले सकता है, और 2) यह मानता है कि आपके डेटा के बीच हैशिंग टकराव दुर्लभ हैं।
यह एक जनरेटर अभिव्यक्ति जैसे सूचियों, पर यात्रा प्रदर्शन उपयोग कर रहा है करने के लिए दूसरा तरीका:
any(i in a for i in b)
यह इसलिए कोई नया स्मृति मध्यस्थ चर के लिए आवंटित किया जाता है, यथा-स्थान खोज करने के लिए अनुमति देता है। यह पहले खोज पर भी बाहर निकलता है। लेकिन in
ऑपरेटर हमेशा O(n)
सूचियों पर (here देखें)।
एक और प्रस्तावित विकल्प, सूची में से एक के माध्यम से एक hybridto पुनरावृति है इस सेट पर सदस्यता के लिए एक सेट में एक दूसरे को और परीक्षण कनवर्ट करते हैं, तो जैसे:
a = set(a); any(i in a for i in b)
चौथा दृष्टिकोण का लाभ लेने के लिए है (जमे हुए) सेट (here देखें) की isdisjoint()
विधि, उदाहरण के लिए:
not set(a).isdisjoint(b)
तत्वों आप खोज एक सरणी की शुरुआत (उदाहरण के लिए यह क्रमबद्ध किया जाता है) के पास रखते हैं, जनरेटर अभिव्यक्ति के रूप में, इष्ट है सेट मुझे चौराहे मध्यस्थ चर के लिए नई स्मृति को आबंटित करने के लिए है Thod:
from timeit import timeit
>>> timeit('bool(set(a) & set(b))', setup="a=list(range(1000));b=list(range(1000))", number=100000)
26.077727576019242
>>> timeit('any(i in a for i in b)', setup="a=list(range(1000));b=list(range(1000))", number=100000)
0.16220548999262974
यहाँ सूची के आकार के समारोह में इस उदाहरण के लिए निष्पादन समय का ग्राफ है:
ध्यान दें कि दोनों अक्ष लघुगणक हैं। यह जनरेटर अभिव्यक्ति के लिए सबसे अच्छा मामला दर्शाता है। जैसा कि देखा जा सकता है, isdisjoint()
विधि बहुत छोटी सूची आकारों के लिए बेहतर है, जबकि जेनरेटर अभिव्यक्ति बड़ी सूची आकारों के लिए बेहतर है।
दूसरी तरफ, खोज हाइब्रिड और जनरेटर अभिव्यक्ति की शुरुआत के साथ शुरू होती है, यदि साझा तत्व सरणी के अंत में व्यवस्थित रूप से प्रारंभ होता है (या दोनों सूचियां किसी भी मान को साझा नहीं करती हैं), विवाद और सेट चौराहे के दृष्टिकोण जेनरेटर अभिव्यक्ति और हाइब्रिड दृष्टिकोण से तेज़ तरीके से होते हैं।
>>> timeit('any(i in a for i in b)', setup="a=list(range(1000));b=[x+998 for x in range(999,0,-1)]", number=1000))
13.739536046981812
>>> timeit('bool(set(a) & set(b))', setup="a=list(range(1000));b=[x+998 for x in range(999,0,-1)]", number=1000))
0.08102107048034668
यह ध्यान रखें कि जनरेटर अभिव्यक्ति तरीका बड़ा सूची आकार के लिए धीमी है दिलचस्प है। यह पिछले आंकड़े के लिए 100000 की बजाय 1000 पुनरावृत्ति के लिए है। यह सेटअप तब भी अनुमानित होता है जब कोई तत्व साझा नहीं किया जाता है, और विवाद और सेट चौराहे के दृष्टिकोण के लिए सबसे अच्छा मामला है। साझा करने के
उच्च मौका:
यहाँ यादृच्छिक संख्या का उपयोग कर (बजाय हेराफेरी सेटअप एक तकनीक या किसी अन्य के पक्ष में) दो विश्लेषण कर रहे हैं तत्वों बेतरतीब ढंग से [1, 2*len(a)]
से लिया जाता है। साझा करने का कम मौका: तत्वों को यादृच्छिक रूप से [1, 1000*len(a)]
से लिया जाता है।
अब तक, यह विश्लेषण माना जाता है कि दोनों सूचियां एक ही आकार के हैं।अन्यथा प्रदर्शन कम हो जाती है
सुनिश्चित करें कि a
सूची छोटी है बनाओ,: विभिन्न आकारों की दो सूचियों के मामले में, उदाहरण के लिए a
बहुत छोटा है, isdisjoint()
हमेशा तेज है। इस प्रयोग में, a
सूची आकार 5
पर स्थिर सेट किया गया था।
सारांश में:
- सूचियों बहुत छोटे (< 10 तत्वों) कर रहे हैं,
not set(a).isdisjoint(b)
हमेशा सबसे तेज है।
- यदि सूचियों में तत्वों को क्रमबद्ध किया गया है या नियमित संरचना है जिसका आप लाभ उठा सकते हैं, जेनरेटर अभिव्यक्ति
any(i in a for i in b)
बड़ी सूची आकारों में सबसे तेज़ है;
not set(a).isdisjoint(b)
के साथ सेट चौराहे का परीक्षण करें, जो bool(set(a) & set(b))
से हमेशा तेज़ है।
- हाइब्रिड "सूची के माध्यम से पुनरावृत्ति, सेट पर परीक्षण"
a = set(a); any(i in a for i in b)
आमतौर पर अन्य विधियों की तुलना में धीमी है।
- जनरेटर अभिव्यक्ति और हाइब्रिड तत्वों को साझा किए बिना सूचियों की बात करते समय दो अन्य दृष्टिकोणों की तुलना में बहुत धीमी हैं।
ज्यादातर मामलों में, isdisjoint()
विधि का उपयोग कर जनरेटर अभिव्यक्ति के रूप में सबसे अच्छा तरीका बहुत लंबे समय तक ले, निष्पादित करने के लिए होगा के रूप में यह बहुत अक्षम है जब कोई तत्व साझा कर रहे हैं।
एकमात्र अनुकूलन जो मैं सोच सकता हूं वह 'लेन (...)> 0' छोड़ रहा है क्योंकि' बूल (सेट ([])) 'झूठी पैदा करता है। और निश्चित रूप से यदि आपने अपनी सूचियां सेट के रूप में सेट के रूप में रखी हैं तो आप सेट निर्माण ओवरहेड को सहेज लेंगे। – msw
प्रासंगिक: https://stackoverflow.com/a/44786707/1959808 –
ध्यान दें कि आप '1' से' True' को अलग नहीं कर सकते हैं और '0' से' गलत 'नहीं कर सकते हैं। 'सेट नहीं ([1])। isdisjoint ([True])' अन्य 'समाधानों के साथ' सत्य 'हो जाता है। – Dimali