2009-11-09 3 views
30

list.index(x) फ़ंक्शन पहले आइटम की सूची में अनुक्रमणिका देता है जिसका मान x है।पायथन: एक सूची के पहले तत्व की अनुक्रमणिका लौटाएं जो एक पारित कार्य को सही बनाता है

एक फ़ंक्शन, list_func_index() है, जो index() फ़ंक्शन के समान है जिसमें एक पैरामीटर के रूप में f() फ़ंक्शन है। फ़ंक्शन, f() प्रत्येक तत्व, e पर सूचीबद्ध है, सूची के f(e)True पर लौटाता है। तो list_func_index()e की अनुक्रमणिका देता है।

codewise:

>>> def list_func_index(lst, func): 
     for i in range(len(lst)): 
     if func(lst[i]): 
      return i 
     raise ValueError('no element making func True') 

>>> l = [8,10,4,5,7] 
>>> def is_odd(x): return x % 2 != 0 
>>> list_func_index(l,is_odd) 
3 

वहाँ एक और अधिक सुरुचिपूर्ण समाधान है? (और समारोह के लिए एक बेहतर नाम)

उत्तर

54

आप कर सकता है कि एक जनरेटर का उपयोग एक लाइनर में:

(i for i,v in enumerate(l) if is_odd(v)).next() 

जनरेटर के बारे में अच्छी बात यह है कि वे केवल अनुरोध राशि से ऊपर की गणना है। तो पहले दो सूचकांकों का अनुरोध (लगभग) बस के रूप में आसान है:

y = (i for i,v in enumerate(l) if is_odd(v)) 
x1 = y.next() 
x2 = y.next() 

हालांकि, पिछले सूचकांक के बाद एक StopIteration अपवाद उम्मीद (जो है कैसे जनरेटर काम करते हैं)। यह आपके "टेक-फर्स्ट" दृष्टिकोण में भी सुविधाजनक है, यह जानने के लिए कि ऐसा कोई मूल्य नहीं मिला --- list.index() फ़ंक्शन यहां ValueError फेंक देगा।

अतिरिक्त एलेक्स मार्टेली से उल्लेख के लायक एक टिप्पणी: अप अजगर 2.6 में और, next(someiterator)someiterator.next() से अधिक नए और पसंदीदा तरीका है।

+0

+1 जो मैं टाइपिंग के बीच में था :-) – bobince

+7

वाह, अस्पष्टता के लिए एक और जीत। इस तरह के "चालाक" कोड का उपयोग करने से प्राप्त करने के लिए कुछ भी नहीं है। –

+0

@ जेएफ: वास्तव में यह आपके समाधान का लगभग एक साक्षर प्रतिलेखन है, केवल "def" के बजाय ब्रेसिज़ के साथ। अंत में बदले में वापसी मूल्य सामने है (एक फायदा, मैं कहूंगा)। और उसके बाद कई उत्तरों लेने का विकल्प भी है, आपका समाधान कुछ नहीं कर सकता है। तो आपके प्रतिद्वंद्वी के जवाब को कम करने के लिए वास्तव में क्या कारण है? – Paul

8

एक संभावना यह है निर्मित enumerate समारोह:

def index_of_first(lst, pred): 
    for i,v in enumerate(lst): 
     if pred(v): 
      return i 
    return None 

यह एक आप एक "विधेय" के रूप में वर्णन की तरह एक समारोह का उल्लेख करने के ठेठ है, यह कुछ सवाल के लिए सच या गलत देता है। यही कारण है कि मैं इसे अपने उदाहरण में pred कहता हूं।

मुझे यह भी लगता है कि यह None वापस करने के लिए बेहतर फॉर्म होगा, क्योंकि यह सवाल का असली जवाब है। यदि आवश्यक हो तो कॉलर None पर विस्फोट करना चुन सकता है।

+1

अधिक सुरुचिपूर्ण, बेहतर नाम है, वास्तव में – bandana

+0

मुझे लगता है कि ओपी ValueError को ऊपर उठाने अगर दिए गए मूल्य नहीं मिला है के सूचकांक के व्यवहार अनुकरण करना चाहता था। अंक के लिए – PaulMcG

+0

+1 जो मेरा एक बड़ा पसंदीदा है। मुझे आखिरी बार याद नहीं आया कि मुझे वास्तव में एक इंडेक्स वैरिएबल को पुरानी शैली के सी तरीके को पायथन में बनाए रखना था। –

0

आप एक सूची-समझ के साथ ऐसा कर सकता है:

l = [8,10,4,5,7] 
filterl = [a for a in l if a % 2 != 0] 

फिर filterl अभिव्यक्ति एक% 2 = 0. मैं एक और अधिक सुरुचिपूर्ण विधि कहेंगे पूरा सूची के सभी सदस्यों को वापस आ जाएगी ...

+0

क्या आप अपना उत्तर ओपी के फ़ंक्शन की तरह अधिक संपादित कर सकते हैं जिसमें पैरामीटर के रूप में एक सूची और फ़ंक्शन है? – quamrana

+4

यह गलत है। यह मूल्यों की एक सूची देता है, एक एकल सूचकांक नहीं। – recursive

+0

filterl = [a में l के लिए if_odd (ए)] –

3

नहीं एकमात्र फंक्शन है, लेकिन आप यह बहुत आसानी से कर सकते हैं:

>>> test = lambda c: c == 'x' 
>>> data = ['a', 'b', 'c', 'x', 'y', 'z', 'x'] 
>>> map(test, data).index(True) 
3 
>>> 

आप एक बार आप itertools उपयोग कर सकते हैं पर पूरी सूची का मूल्यांकन नहीं करना चाहते, लेकिन यह के रूप में सुंदर नहीं है, तो:

>>> from itertools import imap, ifilter 
>>> from operator import itemgetter 
>>> test = lambda c: c == 'x' 
>>> data = ['a', 'b', 'c', 'x', 'y', 'z'] 
>>> ifilter(itemgetter(1), enumerate(imap(test, data))).next()[0] 
3 
>>> 

बस जनरेटर अभिव्यक्ति का उपयोग करना संभवतः इटारटोल से अधिक पठनीय है।

+0

दुर्भाग्यवश, यह पूरी सूची का मूल्यांकन करता है - पहला समाधान खोजने के दौरान शॉर्ट-सर्किट, जो कि तुरंत समाधान देता है, का समाधान करना अच्छा लगेगा। – PaulMcG

+0

यह जनरेटर समझ के साथ किया जा सकता है। – recursive

9

@ पॉल स्वीकार किए जाते हैं जवाब सबसे अच्छा है, लेकिन यहाँ ज्यादातर मनोरंजन और शिक्षा के उद्देश्यों के लिए एक छोटे से पार्श्व सोच संस्करण है, ...:

>>> class X(object): 
... def __init__(self, pred): self.pred = pred 
... def __eq__(self, other): return self.pred(other) 
... 
>>> l = [8,10,4,5,7] 
>>> def is_odd(x): return x % 2 != 0 
... 
>>> l.index(X(is_odd)) 
3 

अनिवार्य रूप से, X के उद्देश्य "का अर्थ बदलने के लिए है समानता "से सामान्य" से "इस भविष्यवाणी को संतुष्ट करता है", जिससे समानता की जांच के रूप में परिभाषित सभी प्रकार की स्थितियों में भविष्यवाणियों के उपयोग की इजाजत मिलती है - उदाहरण के लिए, यह if any(is_odd(x) for x in l): के बजाय आपको कोड भी देगा, छोटे if X(is_odd) in l: , इत्यादि।

उपयोग करने के लायक है? जब @Paul द्वारा लिया गया कोई अधिक स्पष्ट दृष्टिकोण उतना ही आसान नहीं होता है (विशेष रूप से जब नए, चमकदार अंतर्निहित next पुराने, कम उचित .next विधि के बजाय फ़ंक्शन का उपयोग करने के लिए बदल दिया गया है, जैसा कि मैंने उस उत्तर पर टिप्पणी में सुझाव दिया है), लेकिन ऐसी अन्य स्थितियां हैं जहां (या विचार के अन्य रूप "समानता के अर्थ को ट्विक करें", और शायद अन्य तुलनित्र और/या हैशिंग) उपयुक्त हो सकते हैं। अधिकतर, विचार के बारे में जानने के लायक, इसे एक दिन खरोंच से आविष्कार करने से बचने के लिए ;-)।

+0

अच्छा है! लेकिन हम एक्स "नाम" क्या करेंगे? शायद "कुंजी" की तरह कुछ? क्योंकि यह मुझे l.sort (key = fn) की याद दिलाता है। – Paul

+0

आप इसे लगभग "बराबर" कह सकते हैं, इसलिए लाइन l.index (बराबर (is_odd)) – tgray

+1

पढ़ती है मुझे लगता है कि एलेक्स (स्पष्ट रूप से) सुझाव दिया गया है, 'संतुष्ट', इसके लिए एक अच्छा नाम है। –

1

एलेक्स के उत्तर पर एक भिन्नता। यह विधेय X हर बार जब आप या is_odd उपयोग करना चाहते हैं, जो भी टाइप करने के टाल

>>> class X(object): 
...  def __init__(self, pred): self.pred = pred 
...  def __eq__(self, other): return self.pred(other) 
... 
>>> L = [8,10,4,5,7] 
>>> is_odd = X(lambda x: x%2 != 0) 
>>> L.index(is_odd) 
3 
>>> less_than_six = X(lambda x: x<6) 
>>> L.index(less_than_six) 
2 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^