पहला पायथन सूची सूचकांक x से बड़ा है?


81

किसी सूची में पहला सूचकांक जो x से अधिक है, उसे खोजने का सबसे पाइथोनिक तरीका क्या होगा?

उदाहरण के लिए, साथ

list = [0.5, 0.3, 0.9, 0.8]

कार्यक्रम

f(list, 0.7)

लौटूंगा

2.

57
एक चर नाम के रूप में 'सूची' का उपयोग न करें ...
mshsayem

11
आपका मतलब है "पायथोनिक"। के अनुसार urbandictionary.com/define.php?term=Pythonesque , "pythonesque" का अर्थ है "असली, बेतुका", और मुझे नहीं लगता कि कि मान लीजिए कि आप जो खोज रहे हैं: पी
रॉबर्टो Bonvallet

1
सवाल अस्पष्ट है। जवाब है 2क्योंकि 0.9 > 0.7या क्योंकि 0.8 > 0.7? दूसरे शब्दों में, क्या आप क्रमिक रूप से या बढ़ते मूल्यों के क्रम में खोज रहे हैं?
सर्गेई ओरशान्स्की


मैंने इस प्रश्न को इसके विपरीत करने के बजाय एक डुप्लिकेट के रूप में बंद करने के लिए मतदान किया क्योंकि नया प्रश्न अधिक सामान्य है।
क्रिस्टियन सियुपिटु

जवाबों:


118
next(x[0] for x in enumerate(L) if x[1] > 0.7)

29
+1: हालाँकि मैं मैजिक नंबरों से बचना पसंद करूंगा: अगला (idx for idx, value in enumerate (L) if value> 0.7)
truppo

38
+1 सादगी के लिए और next(), लेकिन शायद पठनीयता के लिए:next(i for i,v in enumerate(L) if v > 0.7)
हार्डी

14
हालांकि यह अच्छा लग रहा है, इस मामले में जहां कोई परिणाम नहीं है एक भ्रामक StopIteration बढ़ाएगा।
विर्जिल द्वापर

3
@Wim: लेकिन फिर आप पूरे अनुक्रम का मूल्यांकन करने के लिए वापस आ जाते हैं। itertools.chain()इस तरह सूचियों को जोड़ने के बजाय उपयोग करें ।
इग्नासियो वाज़केज़-अब्राम्स

3
@ आपको यहां श्रृंखला () की आवश्यकता नहीं है। अगला () दूसरा तर्क स्वीकार करता है:next((i for i, x in enumerate(L) if x > value), -1)
8

35

यदि सूची को क्रमबद्ध किया जाता है, तो bisect.bisect_left(alist, value)बड़ी सूची के लिए तेजी से होता है next(i for i, x in enumerate(alist) if x >= value)


अच्छा उत्तर - यह मेरे लिए एक छोटे से 4 तत्व सॉर्ट की गई सूची का उपयोग करके निश्चित रूप से 5 से 6 गुना अधिक तेज था लेकिन, (निश्चित नहीं कि मैं कोई त्रुटि कर रहा हूं), लेकिन जब मैं इस समय का उपयोग 10000 तत्व के लंबे सूची के साथ कर रहा हूँ मुझे लगता है कि यह सूची बोधगम्य उत्तर के मुकाबले लगभग दोगुना है, हालांकि मैं इसके बारे में हैरान था।
एड्रियन टोमकिन्स

1
@ AdrianTompkins: आपके बेंचमार्क में कुछ गड़बड़ है। bisect_leftO (n n) है, जबकि listcomp हे (n) यानी, जितना बड़ा n, उतना ही अधिक लाभ bisect_left()। मैं के सूचकांक को खोजने के लिए कोशिश की है 500_000में range(10**6)उपयोग करते हुए bisect_left()> 3.75 माइक्रोसेकंड और साथ genexpr का उपयोग कर - next()- [> 51.0 मिलीसेकेंड 10_000बार] धीमी रूप में की उम्मीद।
JFS

16
filter(lambda x: x>.7, seq)[0]

4
-1: तकनीकी रूप से सही होने पर, फ़िल्टर का उपयोग न करें जहां एक सूची की समझ अधिक पठनीय और अधिक प्रदर्शन करने वाली दोनों हो
truppo

फ़िल्टर (लैम्ब्डा x: x [1]> .7, एनुमरेट (seq)) [0] [0] - सरल रैखिक खोज
lowtech

4
अजगर 3 में @truppo फिल्टर एक जनरेटर देता है, तो यह एक सूची समझ से भी बदतर नहीं होना चाहिए? इसके अलावा, मैं इस तरह से गणना समाधान से अधिक पठनीय लगता है।
बुबुइक

एक चीज जो इस बारे में अच्छी नहीं है वह यह है कि आप अपवाद से निपटने में लग जाते हैं यदि seq में कोई आइटम नहीं है ।7 से बड़ा।
ब्रायन सी।

समाधान तकनीकी रूप से गलत है। प्रश्न लेखक ने पूछा कि सूची में तत्व का सूचकांक कैसे खोजना है । लेकिन यह समाधान बदले एक रिकॉर्ड लौटाता है। Python 3.8 में Eventmore यह धीमा है कि bisect_left()(सबसे तेज) और enumerate()
सेर्गेई नेवमेरज़िट्स्की

16
>>> alist= [0.5, 0.3, 0.9, 0.8]
>>> [ n for n,i in enumerate(alist) if i>0.7 ][0]
2

2
यह विफल हो जाएगा अगर 'x' सूची में किसी भी अन्य मूल्य से अधिक है
mshsayem

2
@mshsayem: इस मामले के लिए समस्या को परिभाषित नहीं किया गया है। असफलता सही बात हो सकती है।
S.Lott

@ एस.लूट: अच्छी बात है। यदि सूची में नहीं है तो असफल होना एक चर को निर्दिष्ट करते समय एक समझने योग्य त्रुटि के रूप में होता है IndexError: list index out of range:। index = next[ n for n,i in enumerate(alist) if i>0.7 ]त्रुटि का उपयोग कर देता है NameError: name 'index' is not defined:। nextथोड़ा तेज है: 60 000 नंबरों के लिए समय का अंतर 12.7 एनएस बनाम 11.9 एनएस है।
सिंह



3

1) सामान्य ARGWHERE, सामान्य सूचियाँ

यदि आप सुन्न का उपयोग करने के लिए खुश हैं, तो निम्नलिखित सामान्य सूचियों पर काम करेगा (सॉर्ट या अनसर्टेड):

numpy.argwhere(np.array(searchlist)>x)[0]

या यदि आपको सूची के रूप में उत्तर की आवश्यकता है:

numpy.argwhere(np.array(searchlist)>x).tolist()[0]

या यदि आपको पूर्णांक सूचकांक के रूप में उत्तर की आवश्यकता है:

numpy.argwhere(np.array(searchlist)>x).tolist()[0][0]

2) NUMPY खोजा, क्रमबद्ध सूची (खोज सूचियों के लिए बहुत ही कुशल)

हालाँकि, यदि आपकी खोज सूची को क्रमबद्ध किया जाता है, तो यह फ़ंक्शन np.searchsorted का उपयोग करने के लिए बहुत क्लीनर और अच्छा है :

numpy.searchsorted(searchlist,x)

इस फ़ंक्शन का उपयोग करने के बारे में अच्छी बात यह है कि एकल मान x के लिए खोज करने के साथ-साथ, x भी एक सूची हो सकती है, यानी आप खोजे गए मानों की सूची के लिए सूचकांकों की सूची भी वापस कर सकते हैं [X1, x2, x3 .. xn ], ( और यह इस मामले में एक सूची समझ के सापेक्ष बहुत कुशल है )।


2

जब मेरी सूची बहुत लंबी थी तो मुझे भी ऐसी ही समस्या थी। समझ या फ़िल्टर आधारित समाधान पूरी सूची के माध्यम से चले जाएंगे। itertools.takewhile पहली बार झूठी होने के बाद लूप को तोड़ देगा:

from itertools import takewhile

def f(l, b): return len([x for x in takewhile(lambda x: x[1] <= b, enumerate(l))])

l = [0.5, 0.3, 0.9, 0.8]
f(l, 0.7)

1
आप सिर्फ def f (l, b) क्यों नहीं लिखते: रिटर्न लेन (सूची (takewhile (lambda x: x] x] 1] <= b, enumerate (l)))?
Avo Asatryan

2

मुझे पता है कि पहले से ही बहुत सारे उत्तर हैं, लेकिन मुझे कभी-कभी लगता है कि पायथोनिक शब्द का अनुवाद 'वन-लाइनर' में किया गया है।

जब मुझे लगता है कि एक बेहतर परिभाषा इस उत्तर के करीब है :

"स्पष्ट, संक्षिप्त और बनाए रखने वाले कोड का उत्पादन करने के लिए पायथन भाषा की सुविधाओं को उजागर करना।"

हालांकि उपर्युक्त उत्तरों में से कुछ संक्षिप्त हैं, मुझे उन्हें स्पष्ट नहीं लगता है और यह समझने में थोड़ी देर के लिए एक नौसिखिया प्रोग्रामर ले जाएगा, इसलिए कई कौशल स्तरों से बनी टीम के लिए उन्हें अत्यधिक बनाए रखने की आवश्यकता नहीं है।

l = [0.5, 0.3, 0.9, 0.8]

def f(l, x):
    for i in l:
        if i >x: break
    return l.index(i)


f(l,.7)

या

l = [0.5, 0.3, 0.9, 0.8]

def f(l, x):
    for i in l:
        if i >x: return l.index(i)



f(l,.7)

मुझे लगता है कि ऊपर एक नौसिखिया द्वारा आसानी से समझा जाता है और अभी भी किसी भी अनुभवी अजगर प्रोग्रामर द्वारा स्वीकार किए जाने के लिए पर्याप्त संक्षिप्त है।

मुझे लगता है कि गूंगा कोड लिखना एक सकारात्मक है।


1
>>> f=lambda seq, m: [ii for ii in xrange(0, len(seq)) if seq[ii] > m][0]
>>> f([.5, .3, .9, .8], 0.7)
2

जो काफी स्लिक लग रहा है। लेकिन सैद्धांतिक रूप से यह पूरी सूची को पार कर जाएगा और फिर पहला परिणाम (एक्स से अधिक), सही लौटाएगा? क्या कोई ऐसा तरीका है जो पहला परिणाम खोजने के बाद सीधे बंद हो जाए?
1300 बजे c00kiemonster

पूरी सूची को ट्रेस करने में क्या गलत है? यदि 0.7 से अधिक का पहला मूल्य सूची के अंत के पास है, तो इससे कोई फर्क नहीं पड़ता।
भूतडोग ghost४

3
सच। लेकिन इस विशेष मामले में जिन सूचियों पर मैं फ़ंक्शन का उपयोग करने का इरादा रखता हूं, वे बहुत लंबे हैं, इसलिए मैं चाहूंगा कि जैसे ही कोई मैच मिले,
ट्रेसिंग छोड़ दें

चाहे इसकी लंबी या नहीं, अगर पहली कीमत सूची का अंतिम दूसरा आइटम है, तो आपको वहां पहुंचने के लिए पूरी सूची को पार करना होगा!
भूतडॉग ghost

4
@ ghostdog74: हाँ, लेकिन यह सभी मामलों को सबसे खराब मामलों में नहीं चाहता है।
अंकलबेन्स


-1

इसको आजमाओ:

def Renumerate(l):
    return [(len(l) - x, y) for x,y in enumerate(l)]

उदाहरण कोड:

Renumerate(range(10))

उत्पादन:

(10, 0)
(9, 1)
(8, 2)
(7, 3)
(6, 4)
(5, 5)
(4, 6)
(3, 7)
(2, 8)
(1, 9)

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