2009-11-25 17 views
19

मैं एक साधारण अजगर कार्यक्रम में लिखा हैअजगर: सूची सीमा त्रुटि से बाहर सूचकांक

l=[1,2,3,0,0,1] 
for i in range(0,len(l)): 
     if l[i]==0: 
      l.pop(i) 

यह मैं त्रुटि 'सूची अनुक्रमणिका सीमा से बाहर' देता है लाइन if l[i]==0:

पर डिबगिंग मैं यह पता लगाने सकता है कि बाद i बढ़ रहा है और सूची कम हो रही है।
हालांकि, मेरे पास लूप समाप्ति की स्थिति i < len(l) है। तो मुझे ऐसी त्रुटि क्यों मिल रही है?

+1

"मेरे पास लूप समाप्ति स्थिति है

+1

@ एस लॉट, मैं रेंज (0, लेन()) का मतलब है 'मैं लेन (एल) -1' – atv

+3

तक जाउंगा एक और पायथन टिप - आप बस 'रेंज (लेन (एल)) 'लिखा हो सकता था 0 डिफ़ॉल्ट प्रारंभिक मान है। – abyx

उत्तर

39

आप अपनी सूची l की लंबाई कम कर रहे हैं के रूप में आप इस पर पुनरावृति, इतनी के रूप में आप रेंज बयान में अपने सूचकांक के अंत दृष्टिकोण, उन सूचकांकों में से कुछ अब वैध नहीं हैं।

यह कि आप क्या करना चाहते हैं की तरह लग रहा है है:

l = [x for x in l if x != 0] 

जो तत्व हैं जो शून्य थे में से किसी के बिना l की एक प्रति वापस आ जाएगी (कि आपरेशन एक list comprehension कहा जाता है, वैसे) । आप उस अंतिम भाग को if x तक भी छोटा कर सकते हैं, क्योंकि गैर-शून्य संख्या True पर मूल्यांकन करती है।

वहाँ जिस तरह से आप कोड लिखा है में i < len(l) के एक पाश समाप्ति शर्त के रूप में ऐसी कोई बात है, क्योंकि len(l)पूर्व पाश से पहले गणना की है, न कि प्रत्येक यात्रा पर फिर से मूल्यांकन किया। आप सकता यह इस तरह से लिखते हैं, तथापि:

i = 0 
while i < len(l): 
    if l[i] == 0: 
     l.pop(i) 
    else: 
     i += 1 
14

अभिव्यक्ति len(l) केवल एक बार मूल्यांकन किया जाता है, इस समय range() builtin मूल्यांकन किया जाता है। उस समय निर्मित श्रेणी वस्तु बदलती नहीं है; यह संभवतः ऑब्जेक्ट l के बारे में कुछ भी नहीं जान सकता है।

पीएस l एक मूल्य के लिए एक उदार नाम है! यह संख्या 1, या पूंजी अक्षर I की तरह दिखता है।

5

आप उस पर पुनरावृत्ति करते समय सूची का आकार बदल रहे हैं, जो शायद आप नहीं चाहते हैं और आपकी त्रुटि का कारण है।

संपादित करें: के रूप में दूसरों के जवाब दिए और टिप्पणी की है, सूची comprehensions इस सवाल के जवाब में एक पहली पसंद के रूप में बेहतर और विशेष रूप से इसलिए कर रहे हैं। मैंने इसे इस कारण के लिए एक विकल्प के रूप में पेश किया, और सबसे अच्छा जवाब नहीं होने पर, यह अभी भी समस्या हल करता है।

तो उस नोट पर, आप filter का भी उपयोग कर सकते हैं, जो आपको उस सूची में आइटम का मूल्यांकन करने के लिए फ़ंक्शन कॉल करने की अनुमति देता है, जिसे आप नहीं चाहते हैं।

उदाहरण:

>>> l = [1,2,3,0,0,1] 
>>> filter(lambda x: x > 0, l) 
[1, 2, 3] 

लाइव और जानने के। सरल बेहतर है, सिवाय इसके कि जब आपको जटिल होने की आवश्यकता होती है।

+3

आपको लैम्ब्डा की भी आवश्यकता नहीं है, चूंकि 0 झूठी मूल्यांकन करता है। 'फ़िल्टर (कोई नहीं, एल)' –

+1

वास्तव में उसकी लैम्ब्डा स्थिति गलत है। लेकिन 'फ़िल्टर' के लिए +1। – int3

+0

@ स्टेव लोश - यही मुझे एसओ के बारे में पसंद है ... मुझे इस तरह की छोटी सी छोटी सी चीजें सीखना जिससे मुझे लंबे समय तक कीस्ट्रोक बचा सकें! धन्यवाद! – jathanism

0

मैं अजगर 3.3.5 का उपयोग कर रहा हूं। लूप के दौरान उपयोग करने का उपरोक्त समाधान मेरे लिए काम नहीं करता था। भले ही len(l) के बाद मैंने print (i) डाला, तो मुझे एक त्रुटि मिली। मैंने कमांड लाइन (खोल) में एक ही कोड चलाया [विंडो जो हम फ़ंक्शन चलाते समय पॉप अप करते हैं] यह त्रुटि के बिना चलता है।मैंने जो किया वह मुख्य कार्यक्रम में फ़ंक्शन के बाहर लेन (एल) की गणना की गई और लंबाई को पैरामीटर के रूप में पारित किया गया। इसने काम कर दिया। पाइथन कभी-कभी अजीब है।

0

समस्या यह थी कि आपने उस सूची को संशोधित करने का प्रयास किया था जिसे आप लूप के भीतर संदर्भित कर रहे थे जो सूची len() का उपयोग करती थी। जब आप सूची से आइटम को हटाते हैं, तो नया len() अगले लूप पर गणना की जाती है।

उदाहरण के लिए, पहले रन के बाद, जब आपने (i) को l.pop(i) का उपयोग करके हटा दिया, तो सफलतापूर्वक हुआ लेकिन अगले लूप पर सूची की लंबाई बदल गई है, इसलिए सभी इंडेक्स नंबरों को स्थानांतरित कर दिया गया है। एक निश्चित बिंदु पर लूप त्रुटि को फेंकने वाली छोटी सूची में भागने का प्रयास करता है।

लूप कार्यों के बाहर ऐसा करना, हालांकि लूप से पहले पहली घोषणा और खाली सूची द्वारा निर्माण और नई सूची बनाना बेहतर होगा, और बाद में लूप के भीतर आप जो कुछ भी नई सूची में रखना चाहते हैं उसे जोड़ दें।

आप में से उन लोगों के लिए जो एक ही समस्या में आ सकते हैं।

3

क्या Mark Rushakoff कहा गया है सत्य है, लेकिन यदि आप विपरीत दिशा में पुनरावृत्त करते हैं, तो फॉर-लूप में सूची से तत्वों को भी निकालना संभव है। जैसे,

x = [1,2,3,0,0,1] 
for i in range(len(x)-1, -1, -1): 
    if x[i] == 0: 
     x.pop(i) 

यह एक ऊंची इमारत है कि ऊपर से नीचे तक गिर जाता है की तरह है: भले ही वह पतन के बीच में है, तब भी आप इसे में "दर्ज" और अभी तक जा-ढह फर्श पर जा सकते हैं।

0

सूची समझ आपको समाधान के लिए ले जाएगी।

लेकिन पाइथन में ऑब्जेक्ट की प्रतिलिपि बनाने का सही तरीका python module copy - शालो और गहरी प्रतिलिपि संचालन का उपयोग कर रहा है।

l=[1,2,3,0,0,1] 
for i in range(0,len(l)): 
    if l[i]==0: 
     l.pop(i) 
, तो इसके बजाय इस बात का

,

import copy 
l=[1,2,3,0,0,1] 
duplicate_l = copy.copy(l) 
for i in range(0,len(l)): 
    if l[i]==0: 
     m.remove(i) 
l = m 

फिर, अपने खुद के कोड काम किया होता। लेकिन अनुकूलन के लिए, सूची समझ एक अच्छा समाधान है।

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