2011-02-10 5 views
5

में किसी सूची से तत्वों को सुरक्षित रूप से कैसे निकालें I सूची के माध्यम से लूप करें और मेरी स्थिति को पूरा करने वाले तत्वों को हटा दें। लेकिन यह काम क्यों नहीं करता है, जैसा कि नीचे बताया गया है? धन्यवाद।पायथन

>>> a=[ i for i in range(4)] 
>>> a 
[0, 1, 2, 3] 
>>> for e in a: 
...  if (e > 1) and (e < 4): 
...   a.remove(e) 
... 
>>> a 
[0, 1, 3] 
>>> a=[ i for i in range(4)] 
>>> for e in a: 
...  if (e > -1) and (e < 3): 
...   a.remove(e) 
... 
>>> a 
[1, 3] 

उत्तर

9

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

इसके बजाय, एक प्रतिलिपि (for e in a[:]: ...) पर फिर से चालू करें या मौजूदा सूची को संशोधित करने के बजाय, इसे इच्छित वस्तुओं ([e for e in a if ...]) वाली एक नई सूची प्राप्त करने के लिए फ़िल्टर करें। ध्यान दें कि कई मामलों में, आपको फ़िल्टर करने के लिए फिर से पुनरावृत्ति करने की आवश्यकता नहीं है, केवल डेटा की पीढ़ी के साथ फ़िल्टरिंग मर्ज करें।

5

आप शुरुआत में सूची समझ में ऐसा क्यों नहीं करते हैं? जैसे

[i for i in range(4) if i <= 1 or i >= 4] 

आप मौजूदा सूची से एक नई सूची बनाने के लिए इसका भी उपयोग कर सकते हैं, उदा।

[x for x in a if x <= 1 or x >= 4] 
+0

यह उन चीज़ों को वापस देता है जिन्हें वास्तव में हटाया जाना चाहिए। –

+0

@ सेवन क्षमा करें, मैं इसे ठीक कर दूंगा –

1

हालांकि इसे पुनरावृत्ति करते समय सूची से तत्वों को निकालना सुरक्षित नहीं है। इसके लिए फ़िल्टर फ़ंक्शन मौजूद है। यह एक फ़ंक्शन लेता है (जो एक तर्क स्वीकार करता है) और एक पुनरावृत्त (इस मामले में आपकी सूची)।

आपके मामले में आप इस तरह एक लैम्ब्डा समारोह का उपयोग कर सकते हैं::

a = filter(lambda x: x > 1 and x < 4, range(4)) 

यह एक नए तत्व जहां समारोह उस तत्व के लिए लागू किया लौटे सच के साथ एक ही प्रकार के iterable (सूची फिर से यहाँ) रिटर्न या यदि आप पहले से ही सूची है:

a = range(4) 
a = filter(lambda x: x > 1 and x < 4, a) 

याद रखें कि यदि python3 उपयोग कर रहे हैं यह एक इटरेटर और नहीं एक सूची प्रदान करेगा।

+0

इस तरह के साधारण मामलों के लिए, मैं 'फ़िल्टर' पर एक सूची समझना पसंद करूंगा। –

2

फ़िल्टरिंग का विचार एक अच्छा है, हालांकि यह उस बिंदु को याद करता है जो कुछ सूचियां बहुत बड़ी हो सकती हैं और निकालने के लिए तत्वों की संख्या बहुत छोटी हो सकती है।

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

+0

कहें कि आपके पास 1 मिलियन तत्व सूची है और 4 हटा दी गई है। इसे फ़िल्टर करने का अर्थ है लगभग 1,000,000 तत्वों को झुकाव, जबकि आपके सुझाव में औसतन दो गुना अधिक शफल होना शामिल होगा। बेशक अन्य कारकों का मतलब यह होगा कि यह उतना आसान नहीं है, लेकिन जब तक कि आप वास्तव में कोड का समय नहीं लगाते हैं, मैं सबसे सरल (फ़िल्टरिंग) के साथ छड़ी कहूंगा क्योंकि आप इसे और अधिक बनाकर कुछ हासिल नहीं करेंगे जटिल। – Duncan

+0

मैं तत्वों को "shuffling" होने पर विचार नहीं करता। और अंत में, आपके पास 4 तत्वों की एक सूची है जो आप विपरीत क्रम में पुनरावृत्त करते हैं, और हटाने में सूची तत्वों को अनलिंक करना शामिल है, तो फिर, शफल कहां है? ग़लत विवरण समझाए जाने के लिए –

2

इसे देखने का सबसे आसान तरीका वास्तविक वस्तुओं की बजाय सूची-ऑफसेट पर काम करने वाले पुनरावृत्ति के बारे में सोचना है - पहले आइटम में कुछ करें, फिर दूसरा आइटम, फिर तीसरा आइटम, जब तक यह आइटम से बाहर नहीं हो जाता ।

1 
4 
[1,3,4] 

में

lst = [1,2,3,4] 
for item in lst: 
    if item==2: 
     lst.remove(item) 
    else: 
     print item 
print lst 

परिणाम जो समझ में आता है अगर आप ऐसा है जैसे कि यह माध्यम से कदम: यदि आप सूची में आइटम्स की संख्या बदलते हैं, तो यह सूची में सभी शेष वस्तुओं के ऑफसेट में परिवर्तन :

[1,2,3,4] 
^ 
first item is not 2, so print it -> 1 

[1,2,3,4] 
^
    second item is 2, so remove it 

[1,3,4] 
    ^
    third item is 4, so print it -> 4 

केवल वास्तविक समाधान जब आप इसे से अधिक पुनरावृत्ति कर रहे हैं सूची में आइटम्स की संख्या में परिवर्तन नहीं है। उन आइटम्स की प्रतिलिपि बनाएं जिन्हें आप एक नई सूची में रखना चाहते हैं, या उन मानों का ट्रैक रखें जिन्हें आप निकालना चाहते हैं और अलग-अलग पास में हटा-दर-मान करें।

+0

+1। – delnan