जाँच करें कि पायथन में कोई सूची में कुछ है (नहीं)


314

मेरे पास पायथन में ट्यूपल्स की एक सूची है , और मेरी एक शर्त है कि जहां मैं केवल शाखा लेना चाहता हूं यदि ट्यूपल सूची में नहीं है (यदि यह सूची में है, तो मैं शाखा नहीं लेना चाहता)

if curr_x -1 > 0 and (curr_x-1 , curr_y) not in myList: 

    # Do Something

हालांकि यह वास्तव में मेरे लिए काम नहीं कर रहा है। मैंने क्या गल्त किया है?


1
ध्यान दें कि 3 -1 > 0 and (4-1 , 5) not in []that Trueइसलिए त्रुटि ऑपरेटर पूर्वता में से एक नहीं है।
दान डी।

6
"वास्तव में मेरे लिए काम नहीं करने" से आपका क्या मतलब है? आप क्या होने की उम्मीद करते हैं? वास्तव में क्या होता है? क्या सटीक सूची सामग्री समस्या को ट्रिगर करती है?
कार्ल केनचेल

क्यों नहीं की कोशिश करें myList.count((curr_x, curr_y)), अगर (curr_x, curr_y)में नहीं है myList, तो परिणाम होगा0
LittleLittleQ


2
यह "मेरा कोड वास्तव में मेरे लिए कैसे काम नहीं कर रहा है" प्रश्न को 297 अपवोट मिला? कृपया हमें एक न्यूनतम प्रतिलिपि प्रस्तुत करने योग्य उदाहरण दें
गेरिट

जवाबों:


502

बग शायद आपके कोड में कहीं और है, क्योंकि इसे ठीक काम करना चाहिए:

>>> 3 not in [2, 3, 4]
False
>>> 3 not in [4, 5, 6]
True

या टुपल्स के साथ:

>>> (2, 3) not in [(2, 3), (5, 6), (9, 1)]
False
>>> (2, 3) not in [(2, 7), (7, 3), "hi"]
True

11
@Zack: यदि आपको इस बारे में पता नहीं था, तो आप बस कर सकते हैंif not ELEMENT in COLLECTION:
Ninjagecko

@ninjagecko: कंटेनर प्रकार पर निर्भर करता है जो कम कुशल, या गलत भी हो सकता है। उदाहरण के लिए देखें ब्लूम फ़िल्टर
orlp

14
@ नाइटक्रैकर कोई मतलब नहीं है जो A not in Bकरने के लिए कम है not B.__contains__(A)जो वही not A in Bहै जो कम हो गया है not B.__contains__(A)
दान डी।

1
अरे वाह, मैं कसम खा सकता था कि अजगर कुछ ऐसा था __notcontains__। मुझे क्षमा करें, फिर मैंने जो कहा वह बकवास है।
orlp

2
@ std''OrgnlDave एकमात्र तरीका जो हो सकता है, अगर notइससे उच्चतर पूर्वता है, inजिसमें यह नहीं है। परिणाम की पर विचार करें ast.dump(ast.parse("not A in B").body[0]), जिसमें परिणाम "Expr(value=UnaryOp(op=Not(), operand=Compare(left=Name(id='A', ctx=Load()), ops=[In()], comparators=[Name(id='B', ctx=Load())])))"तो notएक को कस कर वर्गीकृत किया, एक परिणाम की उम्मीद है | होना करने के लिए "Expr(value=Compare(left=UnaryOp(op=Not(), operand=Name(id='A', ctx=Load())), ops=[In()], comparators=[Name(id='B', ctx=Load())]))", जिसके लिए पार्स है "(not A) in B"
दान डी।

20

पायथन की सूची में कुछ (नहीं) है तो मैं कैसे जांच करूं?

सबसे सस्ता और सबसे पठनीय समाधान inऑपरेटर (या आपके विशिष्ट मामले में not in) का उपयोग कर रहा है। जैसा कि प्रलेखन में उल्लेख किया गया है,

ऑपरेटरों inऔर not inसदस्यता के लिए परीक्षण। x in sका मूल्यांकन Trueकरता है, तो xके एक सदस्य है s, और Falseनहीं तो। x not in sकी उपेक्षा लौटाता है x in s

साथ ही,

ऑपरेटर not inका व्युत्क्रम सही मान होता है in

y not in xतार्किक रूप में ही है not y in x

कुछ उदाहरण निम्नलिखित हैं:

'a' in [1, 2, 3]
# False

'c' in ['a', 'b', 'c']
# True

'a' not in [1, 2, 3]
# True

'c' not in ['a', 'b', 'c']
# False

यह भी tuples के साथ काम करता है, क्योंकि tuples hashable (इस तथ्य के परिणामस्वरूप कि वे अपरिवर्तनीय भी हैं):

(1, 2) in [(3, 4), (1, 2)]
#  True

यदि RHS पर ऑब्जेक्ट एक __contains__()विधि को परिभाषित करता है , inतो आंतरिक रूप से इसे कॉल करेगा, जैसा कि डॉक्स के तुलना अनुभाग के अंतिम पैराग्राफ में उल्लेख किया गया है ।

... inऔर not inप्रकार से समर्थित हैं जो चलने योग्य हैं या __contains__()विधि को लागू करते हैं । उदाहरण के लिए, आप ऐसा कर सकते हैं (लेकिन ऐसा नहीं करना चाहिए):

[3, 2, 1].__contains__(1)
# True

inशॉर्ट-सर्किट, इसलिए यदि आपका तत्व सूची की शुरुआत में है, तो inतेजी से मूल्यांकन करता है:

lst = list(range(10001))
%timeit 1 in lst
%timeit 10000 in lst  # Expected to take longer time.

68.9 ns ± 0.613 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
178 µs ± 5.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

यदि आप किसी आइटम की सूची में है या नहीं, इससे अधिक जांच करना चाहते हैं, तो विकल्प हैं:

  • list.indexएक आइटम के सूचकांक को पुनः प्राप्त करने के लिए इस्तेमाल किया जा सकता है। यदि वह तत्व मौजूद नहीं है, तो एक ValueErrorउठाया जाता है।
  • list.count यदि आप घटनाओं को गिनना चाहते हैं तो इसका उपयोग किया जा सकता है।

XY समस्या: क्या आपने विचार किया है set?

अपने आप से ये सवाल पूछें:

  • क्या आपको यह जांचने की आवश्यकता है कि क्या आइटम एक बार से अधिक सूची में है?
  • क्या यह जांच लूप के अंदर की गई है, या किसी फ़ंक्शन को बार-बार कहा जाता है?
  • क्या वे आइटम जो आप अपनी सूची में धोने योग्य हैं? IOW, क्या आप hashउन पर कॉल कर सकते हैं?

यदि आपने इन सवालों के "हां" का जवाब दिया है, तो आपको setइसके बजाय उपयोग करना चाहिए । S inपर एक सदस्यता परीक्षण listO (n) समय जटिलता है। इसका मतलब है कि अजगर को आपकी सूची का एक रेखीय स्कैन करना होगा, प्रत्येक तत्व का दौरा करना होगा और इसे खोज आइटम के खिलाफ तुलना करना होगा। यदि आप इसे बार-बार कर रहे हैं, या यदि सूचियाँ बड़ी हैं, तो यह ऑपरेशन ओवरहेड हो जाएगा।

setदूसरी ओर, वस्तुओं ने निरंतर समय की सदस्यता जांच के लिए अपने मूल्यों को हैश किया है। चेक का उपयोग करके भी किया जाता है in:

1 in {1, 2, 3} 
# True

'a' not in {'a', 'b', 'c'}
# False

(1, 2) in {('a', 'c'), (1, 2)}
# True

यदि आप काफी दुर्भाग्यशाली हैं कि जिस तत्व को आप खोज रहे हैं / नहीं खोज रहे हैं वह आपकी सूची के अंत में है, तो अजगर ने सूची को अंत तक स्कैन किया होगा। यह नीचे दिए गए समय से स्पष्ट है:

l = list(range(100001))
s = set(l)

%timeit 100000 in l
%timeit 100000 in s

2.58 ms ± 58.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
101 ns ± 9.53 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

एक अनुस्मारक के रूप में, यह एक उपयुक्त विकल्प है जब तक आपके द्वारा संग्रहीत और देख रहे तत्वों को धोने योग्य है। IOW, उन्हें या तो अपरिवर्तनीय प्रकार, या वस्तुओं को लागू करना होगा __hash__


2
सेट हमेशा एक विकल्प नहीं होते हैं (उदाहरण के लिए, जब उत्परिवर्तनीय वस्तुओं की सूची होती है)। बड़े संग्रह के लिए: लुकअप के लिए सेट का निर्माण वैसे भी O (n) समय है और आपकी मेमोरी के उपयोग को दोगुना कर सकता है। यदि आपके पास पहले से कोई लुकअप नहीं है, तो इसे बनाना / बनाए रखना हमेशा सबसे अच्छा विकल्प नहीं है।
विम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.