अजगर में list.index (संभवत: मौजूद नहीं) को संभालने का सबसे अच्छा तरीका है


113

मेरे पास कोड है जो कुछ इस तरह दिखता है:

thing_index = thing_list.index(thing)
otherfunction(thing_list, thing_index)

ठीक है, इसलिए यह सरल है लेकिन आपको इसका विचार है। अब thingवास्तव में सूची में नहीं हो सकता है, जिस स्थिति में मैं -1 पास करना चाहता हूं thing_index। अन्य भाषाओं में यह वही है जो आप index()वापस लौटने की उम्मीद करेंगे अगर यह तत्व नहीं मिला। वास्तव में यह एक फेंकता है ValueError

मैं ऐसा कर सकता था:

try:
    thing_index = thing_list.index(thing)
except ValueError:
    thing_index = -1
otherfunction(thing_list, thing_index)

लेकिन यह गंदा लगता है, साथ ही मुझे नहीं पता कि ValueErrorक्या किसी और कारण से उठाया जा सकता है। मैं जनरेटर कार्यों के आधार पर निम्नलिखित समाधान के साथ आया था, लेकिन यह थोड़ा जटिल लगता है:

thing_index = ( [(i for i in xrange(len(thing_list)) if thing_list[i]==thing)] or [-1] )[0]

क्या एक ही तरीके से प्राप्त करने के लिए एक क्लीनर तरीका है? मान लें कि सूची क्रमबद्ध नहीं है।


4
"... किस स्थिति में मैं -1 पास करना चाहता हूं thing_index।" - यह निश्चित रूप से संयुक्त राष्ट्र के पाइथोनिक है। एक ऑपरेशन के सफल न होने की स्थिति में (अर्थहीन) टोकन मूल्य पास करना - पर अपवाद है - अपवाद वास्तव में यहाँ सही तरीका है। विशेष रूप से चूंकि thing_list[-1]एक वैध अभिव्यक्ति है, जिसका अर्थ सूची में अंतिम प्रविष्टि है।
टिम पीटरज़

@jellybean: facepalm पी: ... स्पॉट जावा सांकेतिक शब्दों में बदलनेवाला
Draemon

4
@ समय: ऐसा str.findतरीका है जो वास्तव में ऐसा करता है: -1जब विषय में सुई नहीं मिलती है तो वह वापस लौटता है।
साइलेंटगॉस्ट

@ कोई भी तो बेहतर होगा ... और यह तानाशाही [कुंजी] बनाम तानाशाह [कुंजी] के अनुरूप होगा
ड्रेमन

@SilentGhost: एचएम, दिलचस्प। मुझे इस पर अधिक विस्तार से गौर करना होगा। str.index()यदि खोज स्ट्रिंग नहीं मिली है तो एक अपवाद को फेंक दें।
टिम पीटरज़

जवाबों:


65

कोशिश-सिवाय क्लॉज का उपयोग करने के बारे में "गंदा" कुछ भी नहीं है। यह पाइथोनिक तरीका है। केवल विधि ValueErrorद्वारा उठाया जाएगा .index, क्योंकि यह एकमात्र कोड है जो आपके पास है!

टिप्पणी का जवाब देने के लिए:
पायथन में, अनुमति माँगने की तुलना में क्षमा माँगना आसान है , दर्शन को अच्छी तरह से स्थापित किया गया है, और कोई index भी अन्य मुद्दों के लिए इस प्रकार की त्रुटि नहीं उठाएगा। ऐसा नहीं कि मैं किसी के बारे में सोच सकता हूं।


29
निश्चित रूप से अपवाद असाधारण मामलों के लिए हैं, और यह शायद ही ऐसा है। अगर मुझे यह मूल्य ValueError से अधिक विशिष्ट लगता तो ऐसी समस्या नहीं होती।
ड्रेमन

1
मुझे पता है कि इसे केवल उसी विधि से फेंका जा सकता है लेकिन क्या केवल उसी कारण से इसे फेंकने की गारंटी है ? ऐसा नहीं है कि मैं एक और कारण के बारे में सोच सकता हूं कि सूचकांक विफल हो जाएगा..लेकिन फिर उन चीजों के लिए अपवाद नहीं हैं जिनके बारे में आप नहीं सोच सकते हैं?
ड्रेमन

4
{}.get(index, '')अधिक पायथोनिक नहीं है ? कम पठनीय का उल्लेख नहीं है।
एस्टेबन कुबेर 25'10

1
जब मैं कुंजी की मौजूदगी की उम्मीद करता हूं, तो मैं प्रमुख [कुंजी] का उपयोग करता हूं और जब मुझे यकीन नहीं होता है, तो मैं (चाबी) भूल जाता हूं, और मैं यहां समकक्ष की तलाश कर रहा हूंNone-1 के बजाय वापस लौटना ठीक रहेगा, लेकिन जैसा कि आपने खुद से टिप्पणी की थी, str.find () रिटर्न -1 (इसलिए) क्यों नहीं होना चाहिए। सूची ()) वही काम करता है? मैं "pythonic" तर्क नहीं खरीद रहा हूं
ड्रेमन

3
लेकिन मुद्दा यह है कि सबसे पायथोनिक समाधान केवल कोशिश / उपयोग करने के लिए है और -1 सेंटिनल मान बिल्कुल नहीं है। IE आपको फिर से लिखना चाहिए otherfunction। दूसरी ओर, अगर यह टूटा नहीं है, ...
एंड्रयू जफ

53
thing_index = thing_list.index(elem) if elem in thing_list else -1

एक पंक्ति। सरल। कोई अपवाद नहीं।


35
सरल हाँ, लेकिन यह दो रैखिक खोजों को करेगा और जबकि प्रदर्शन एक मुद्दा नहीं है, जो अत्यधिक लगता है।
ड्रेमन

4
@Draemon: सहमत - जो 2 पास करेगा - लेकिन यह संभावना नहीं है कि एक हजार-लाइन कोड-बेस से यह एक अड़चन होगी। :) एक हमेशा के साथ एक अनिवार्य समाधान के लिए ऑप्ट-इन कर सकते हैं for
एमिल इवानोव

मेमने के साथindexOf = lambda item,list_ : list_.index(item) if item in list_ else -1 # OR None
अला अकेल

17

dictप्रकार एक है getसमारोह है, जहां अगर कुंजी शब्दकोश में मौजूद नहीं है, के लिए 2 तर्क getमान जो इसे वापस चाहिए। इसी तरह setdefault, वह है जो dictकुंजी मौजूद होने पर मान लौटाता है, अन्यथा यह आपके डिफ़ॉल्ट पैरामीटर के अनुसार मान सेट करता है और फिर आपका डिफ़ॉल्ट पैरामीटर लौटाता है।

आप listएक getindexdefaultविधि के प्रकार का विस्तार कर सकते हैं ।

class SuperDuperList(list):
    def getindexdefault(self, elem, default):
        try:
            thing_index = self.index(elem)
            return thing_index
        except ValueError:
            return default

जो तब इस्तेमाल किया जा सकता है जैसे:

mylist = SuperDuperList([0,1,2])
index = mylist.getindexdefault( 'asdf', -1 )

6

आपके कोड का उपयोग करने में कुछ भी गलत नहीं है ValueError। यदि आप अपवादों से बचना चाहते हैं, तो यहां एक और वन-लाइनर है:

thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)

क्या वह अजगर 2.6 है? मुझे पता है कि मैंने इसका उल्लेख नहीं किया था, लेकिन मैं 2.5 का उपयोग कर रहा हूं। यह शायद मैं 2.6 में क्या करूँगा
ड्रेमन

1
@ काम: हाँ, next()पायथन 2.6+ में फ़ंक्शन मौजूद है। लेकिन 2.5 के लिए लागू करना आसान है, अगले
16

4

यह मुद्दा भाषा दर्शन में से एक है। उदाहरण के लिए जावा में हमेशा एक परंपरा रही है कि अपवाद वास्तव में केवल "असाधारण परिस्थितियों" में उपयोग किया जाना चाहिए, जब त्रुटियां हुई हैं, बजाय प्रवाह नियंत्रण के । शुरुआत में यह प्रदर्शन कारणों से था क्योंकि जावा अपवाद धीमा था लेकिन अब यह स्वीकृत शैली बन गई है।

इसके विपरीत, पायथन ने हमेशा सामान्य कार्यक्रम प्रवाह को इंगित करने के लिए अपवादों का उपयोग किया है, जैसे ValueErrorकि हम यहां चर्चा कर रहे हैं। पायथन शैली में इसके बारे में "गंदा" कुछ भी नहीं है और कई और हैं जहां से आया था। एक और भी सामान्य उदाहरण StopIterationअपवाद है जो एक इट्रेटर की next()विधि द्वारा यह संकेत देने के लिए उठाया जाता है कि आगे कोई मान नहीं हैं।


वास्तव में, JDK फेंकता है जिस तरह से भी कई जांचे हुए अपवादों, तो मुझे यकीन है कि ऐसा नहीं है कि दर्शन वास्तव में जावा के लिए लागू किया जाता है हूँ। मेरे पास प्रति-से एक समस्या नहीं है StopIterationक्योंकि यह स्पष्ट रूप से परिभाषित है कि अपवाद का मतलब क्या है। ValueErrorथोड़ा बहुत सामान्य है।
ड्रेमन

मैं इस विचार का उल्लेख कर रहा था कि प्रवाह नियंत्रण के लिए अपवादों का उपयोग नहीं किया जाना चाहिए: c2.com/cgi/wiki?DontUseExceptionForFlowControl , जावा द्वारा जांचे गए अपवादों की इतनी अधिक संख्या नहीं है, जिनकी संपूर्ण चर्चा: mindview.net/Etc/Discussions /
चेकडेक्शंस

4

यदि आप अक्सर ऐसा कर रहे हैं, तो यह बेहतर है कि इसे एक सहायक कार्य में स्टोव करें:

def index_of(val, in_list):
    try:
        return in_list.index(val)
    except ValueError:
        return -1 

4

इस बारे में क्या 😃:

li = [1,2,3,4,5] # create list 

li = dict(zip(li,range(len(li)))) # convert List To Dict 
print( li ) # {1: 0, 2: 1, 3: 2, 4:3 , 5: 4}
li.get(20) # None 
li.get(1)  # 0 

1

इस बारे में क्या:

otherfunction(thing_collection, thing)

एक फ़ंक्शन इंटरफ़ेस में सूची इंडेक्स की तरह कुछ कार्यान्वयन-निर्भरता को उजागर करने के बजाय, संग्रह और चीज़ को पास करें और "सदस्यता के लिए परीक्षण" मुद्दों के साथ अन्य व्यवहार करने दें। अगर अन्य संग्रह को संग्रह-प्रकार-अज्ञेयवादी लिखा जाता है, तो यह संभवतः इसके साथ शुरू होगा:

if thing in thing_collection:
    ... proceed with operation on thing

जो काम करेगा अगर thing_collection एक सूची, टपल, सेट, या तानाशाही है।

यह संभवतः इससे अधिक स्पष्ट है:

if thing_index != MAGIC_VALUE_INDICATING_NOT_A_MEMBER:

जो कोड आपके पास पहले से ही अन्य सुविधाओं में है।


1

इस बारे में क्या:

temp_inx = (L + [x]).index(x) 
inx = temp_inx if temp_inx < len(L) else -1

0

मेरे पास सूचियों पर ".index ()" विधि के साथ एक ही मुद्दा है। मेरे पास इस तथ्य के साथ कोई समस्या नहीं है कि यह एक अपवाद फेंकता है, लेकिन मैं इस तथ्य से पूरी तरह असहमत हूं कि यह एक गैर-वर्णनात्मक मूल्य है। मैं समझ सकता था कि क्या यह एक IndexError होता, हालांकि।

मैं देख सकता हूं कि "-1" लौटाना भी एक मुद्दा होगा क्योंकि यह पायथन में एक वैध सूचकांक है। लेकिन वास्तविक रूप से, मैं एक नकारात्मक संख्या वापस करने के लिए ".index ()" विधि की उम्मीद नहीं करता।

यहाँ एक लाइनर जाता है (ठीक है, यह एक लंबी लाइन है ...), सूची में ठीक एक बार जाता है और यदि आइटम नहीं मिला तो "कोई नहीं" लौटाता है। इसे फिर से लिखने के लिए इसे फिर से लिखना तुच्छ होगा, क्या आपकी इतनी इच्छा होनी चाहिए।

indexOf = lambda list, thing: \
            reduce(lambda acc, (idx, elem): \
                   idx if (acc is None) and elem == thing else acc, list, None)

कैसे इस्तेमाल करे:

>>> indexOf([1,2,3], 4)
>>>
>>> indexOf([1,2,3], 1)
0
>>>

-2

मुझे नहीं पता कि आपको यह क्यों सोचना चाहिए कि यह गंदा है ... अपवाद के कारण? यदि आप एक oneliner चाहते हैं, यहाँ यह है:

thing_index = thing_list.index(elem) if thing_list.count(elem) else -1

लेकिन मैं इसे इस्तेमाल करने के खिलाफ सलाह दूंगा; मुझे लगता है कि रॉस रोजर्स समाधान सबसे अच्छा है, एक वस्तु का उपयोग करके अपने बेतुके व्यवहार को एनकैप्सुलेट करें, भाषा को पठनीयता की कीमत पर अपनी सीमा तक धकेलने की कोशिश न करें।


1
हां, अपवाद के कारण। आपका कोड दो रेखीय खोज करेगा यह नहीं होगा? ऐसा नहीं है कि प्रदर्शन वास्तव में यहां मायने रखता है। SuperDuperList समाधान अच्छा है, लेकिन इस विशेष स्थिति में ओवरकिल की तरह लगता है। मुझे लगता है कि मैं केवल अपवाद को पकड़ कर समाप्त कर दूंगा, लेकिन मैं यह देखना चाहता था कि क्या कोई क्लीनर (मेरी सुंदरता के लिए) था।
ड्रेमन

@Draemon: अच्छी तरह से आप कोड को find()फंक्शन में इनकैप्सुलेट करेंगे और यह सब साफ हो जाएगा;)
SilentGhost

1
यह उत्सुक है कि मेरे उत्तर में दो डाउनवोट हैं, जबकि एमिल इवानोव का, जबकि शब्दार्थ समान है, सबसे उत्थान में से एक है। ज्यादातर शायद ऐसा इसलिए होता है क्योंकि मेरा काम धीमा है, क्योंकि मैंने "ऑपरेटर" के बजाय गिनती () को नियोजित किया है ... कम से कम एक टिप्पणी जो महान रही होगी, हालांकि :-)
एलन फ्रांजोनी

-2

मैं सुझाव देता हूं:

if thing in thing_list:
  list_index = -1
else:
  list_index = thing_list.index(thing)

2
इस समाधान के साथ समस्या यह है कि "-1" सूची के लिए एक वैध सूचकांक है (अंतिम सूचकांक; अंत से पहला)। इसे संभालने का बेहतर तरीका आपकी स्थिति की पहली शाखा में गलत रिटर्न होगा।
FanaticD
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.