पुनरावृत्ति करते समय सूची से आइटम कैसे निकालें?


934

मैं पायथन में ट्यूपल्स की सूची पर ध्यान केंद्रित कर रहा हूं, और अगर वे कुछ मानदंडों को पूरा करते हैं तो उन्हें हटाने का प्रयास कर रहा हूं।

for tup in somelist:
    if determine(tup):
         code_to_remove_tup

के स्थान पर मुझे क्या उपयोग करना चाहिए code_to_remove_tup? मैं समझ नहीं पा रहा हूं कि इस फैशन में आइटम को कैसे हटाया जाए।


इस पृष्ठ पर अधिकांश उत्तर वास्तव में यह नहीं समझाते हैं कि किसी सूची पर पुनरावृत्ति करते समय तत्वों को हटाने से अजीब परिणाम क्यों उत्पन्न होते हैं, लेकिन इस प्रश्न में स्वीकृत उत्तर क्या करता है , और शायद शुरुआती लोगों के लिए एक बेहतर तरीका है जो पहली बार इस मुद्दे का सामना करते हैं।
गॉर्जेल डेन्क

जवाबों:


827

आप एक नई सूची बनाने के लिए सूची का उपयोग कर सकते हैं जिसमें केवल वे तत्व हैं जिन्हें आप हटाना नहीं चाहते हैं:

somelist = [x for x in somelist if not determine(x)]

या, स्लाइस को निर्दिष्ट करके somelist[:], आप मौजूदा सूची को केवल आपके इच्छित आइटम समाहित करने के लिए बदल सकते हैं:

somelist[:] = [x for x in somelist if not determine(x)]

यह दृष्टिकोण उपयोगी हो सकता है यदि somelistपरिवर्तन को प्रतिबिंबित करने की आवश्यकता वाले अन्य संदर्भ हैं।

एक समझ के बजाय, आप भी इस्तेमाल कर सकते हैं itertools। पायथन 2 में:

from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)

या पायथन 3 में:

from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)

स्पष्टता के लिए और उन लोगों के लिए जो [:]नोटेशन हैकिश या फ़ज़ी का उपयोग करते हैं , यहां एक अधिक स्पष्ट विकल्प है। सैद्धांतिक रूप से, इसे ऊपर के वन-लाइनर्स की तुलना में अंतरिक्ष और समय के संबंध में एक ही प्रदर्शन करना चाहिए।

temp = []
while somelist:
    x = somelist.pop()
    if not determine(x):
        temp.append(x)
while temp:
    somelist.append(templist.pop())

यह अन्य भाषाओं में भी काम करता है , जिनमें न्यूनतम संशोधनों के साथ पायथन सूचियों की प्रतिस्थापित वस्तुओं की क्षमता नहीं हो सकती है । उदाहरण के लिए, सभी भाषाएँ खाली सूची Falseनहीं डालती हैं जैसा कि पायथन करता है। आप while somelist:कुछ और अधिक स्पष्ट जैसे के लिए स्थानापन्न कर सकते हैं while len(somelist) > 0:


4
क्या आप इसे तेजी से बना सकते हैं यदि आप जानते हैं कि केवल कुछ ही हटाए जाएंगे, अर्थात, केवल उन्हें हटा दें और दूसरों को फिर से लिखने के बजाय अंदर छोड़ दें?
HighBandWidth

20
क्या होगा यदि मेरी सूची बहुत बड़ी है और एक प्रति उपलब्ध नहीं करा सकता है?
jpcgt

15
@jpcgt आपको इसका उपयोग करना चाहिए somelist[:] = (x for x in somelist if determine(x))जिससे कोई भी अनावश्यक प्रतियां नहीं बनाई जा सकती हैं।
रोस्टिस्लाव कोंड्रैतेंको

8
@ रोस्टीस्लावकोंड्रेन्को: list_ass_slice()फ़ंक्शन जो आंतरिक रूप से somelist[:]=कॉल को लागू करता है PySequence_Fast()। यह फ़ंक्शन हमेशा एक सूची देता है अर्थात, @ एलेक्स मार्टेली का समाधान जो पहले से ही एक जनरेटर के बजाय एक सूची का उपयोग करता है वह संभवतः सबसे अधिक कुशल है
jfs

6
क्या आप इस बात की व्याख्या करना चाहेंगे कि सूची और सूची क्लोन कृपया को समझने के बीच अंतर क्या हैं? क्या मूल सूची somelistको दोनों विधियों में परिवर्तित नहीं किया जाएगा?
बॉउन लियू

589

सूची की समझ का सुझाव देने वाले उत्तर ALMOST सही हैं - सिवाय इसके कि वे एक पूरी तरह से नई सूची का निर्माण करें और फिर इसे पुरानी सूची का नाम दें, वे पुरानी सूची को संशोधित नहीं करते हैं। यह चयनात्मक निष्कासन द्वारा आप जो कर रहे हैं, उससे अलग है, जैसा कि @ लेन्नेर्ट के सुझाव में है - यह तेज़ है, लेकिन यदि आपकी सूची को कई संदर्भों के माध्यम से एक्सेस किया जाता है, तो आप इस तथ्य को देखते हैं कि आप केवल एक संदर्भ को फिर से कर रहे हैं और सूची ऑब्जेक्ट को बदल नहीं रहे हैं स्वयं सूक्ष्म, विनाशकारी कीड़े पैदा कर सकता है।

सौभाग्य से, सूची बोध की गति और इन-प्लेस परिवर्तन के आवश्यक शब्दार्थ दोनों को प्राप्त करना बेहद आसान है - बस कोड:

somelist[:] = [tup for tup in somelist if determine(tup)]

अन्य उत्तरों के साथ सूक्ष्म अंतर पर ध्यान दें: यह एक बारनेम को असाइन नहीं कर रहा है - यह एक सूची स्लाइस को असाइन कर रहा है जो कि पूरी सूची में होता है, जिससे केवल एक संदर्भ को दोहराने के बजाय समान पायथन सूची ऑब्जेक्ट के भीतर सूची सामग्री को प्रतिस्थापित किया जाता है। (पिछली सूची ऑब्जेक्ट से नई सूची ऑब्जेक्ट तक) अन्य उत्तरों की तरह।


1
मैं एक तानाशाह के साथ एक ही कटा हुआ असाइनमेंट कैसे करूं? पायथन 2.6 में?
पॉल एमजीजी

11
@Paul: चूँकि dicts अनियंत्रित हैं, स्लाइस dicts के लिए अर्थहीन हैं। यदि आपका डिक्टेट aकी सामग्री को हुक की सामग्री द्वारा प्रतिस्थापित करना चाहते हैं b, तो उपयोग करें a.clear(); a.update(b)
स्वेन मार्नाच

1
वेरिएबल बग का कारण क्या होता है, इसकी जगह ले कर संदर्भों में से एक को acing रीसिट करना ’क्यों हो सकता है? ऐसा लगता है कि केवल बहु-थ्रेडेड अनुप्रयोगों में एक संभावित समस्या होगी, एकल-थ्रेडेड नहीं।
डेरेक दाहर

59
@ डेरेक x = ['foo','bar','baz']; y = x; x = [item for item in x if determine(item)];यह xसूची समझने के परिणाम को फिर से बताता है , लेकिन फिर yभी मूल सूची को संदर्भित करता है ['foo','bar','baz']। यदि आप उम्मीद करते हैं xऔर yउसी सूची को संदर्भित करने के लिए, आपने बग पेश किए होंगे। आप पूरी सूची का एक टुकड़ा असाइन करने से रोकते हैं, जैसा कि एलेक्स दिखाता है, और मैं यहां दिखाता हूं x = ["foo","bar","baz"]; y = x; x[:] = [item for item in x if determine(item)];:। सूची को संशोधित किया गया है। यह सुनिश्चित करना कि सूची (दोनों xऔर yयहां) के सभी संदर्भ नई सूची को संदर्भित करते हैं।
स्टीवन टी। स्नाइडर

वास्तव में, filterफ़ंक्शन का उपयोग करना भी एक नई सूची बनाता है, जगह में तत्वों को संशोधित नहीं करता है ... केवलolist[:] = [i for i in olist if not dislike(i)]
जॉन स्ट्रॉड

302

आपको सूची की एक प्रति लेने की आवश्यकता है और पहले उस पर पुनरावृति करें, या जो अप्रत्याशित परिणाम हो सकते हैं, उसके साथ पुनरावृत्ति विफल हो जाएगी।

उदाहरण के लिए (किस प्रकार की सूची पर निर्भर करता है):

for tup in somelist[:]:
    etc....

एक उदाहरण:

>>> somelist = range(10)
>>> for x in somelist:
...     somelist.remove(x)
>>> somelist
[1, 3, 5, 7, 9]

>>> somelist = range(10)
>>> for x in somelist[:]:
...     somelist.remove(x)
>>> somelist
[]

13
@Zen क्योंकि दूसरा एक सूची की एक प्रति से अधिक है। इसलिए जब आप मूल सूची को संशोधित करते हैं, तो आप उस प्रतिलिपि को संशोधित नहीं करते हैं जिसे आप ओवररेट करते हैं।
लेन्नर्ट रेगेब्र

3
सूची (सोमेलिस्ट) की तुलना में सोमेलिस्ट [:] करने में बेहतर क्या है?
मारियस जमरो

3
list(somelist)एक पुनरावृत्ति को सूची में परिवर्तित कर देगा। somelist[:]किसी ऑब्जेक्ट की प्रतिलिपि बनाता है जो स्लाइसिंग का समर्थन करता है। इसलिए वे जरूरी नहीं कि एक ही काम करते हैं। इस मामले में मैं somelistवस्तु की एक प्रतिलिपि बनाना चाहता हूं , इसलिए मैं उपयोग करता हूं[:]
लेन्नर्ट रेगेब्र

33
इसे पढ़ने वाले किसी भी व्यक्ति पर ध्यान दें, यह सूचियों के लिए बहुत धीमा है। remove()हर पुनरावृत्ति के लिए WHOLE सूची पर जाना है, इसलिए यह हमेशा के लिए ले जाएगा।
vitiral

7
केवल एक दर्जन वस्तुओं की सूची के साथ काम करते समय बिग ओ का समय मायने नहीं रखता। भविष्य के प्रोग्रामर के लिए अक्सर स्पष्ट और सरल प्रदर्शन से कहीं अधिक मूल्यवान है।
स्टीव

127
for i in range(len(somelist) - 1, -1, -1):
    if some_condition(somelist, i):
        del somelist[i]

आपको पीछे की ओर जाने की आवश्यकता है अन्यथा यह पेड़-शाखा को बंद करने जैसा है जिसे आप बैठे हुए हैं :-)

अजगर 2 उपयोगकर्ताओं: की जगह rangeसे xrangeएक हार्डकोडेड सूची बनाने से बचना


13
अजगर के हाल के संस्करणों में, आप का उपयोग करके और भी अधिक सफाई से यह कर सकते हैं reversed()निर्मित
ncoghlan

16
उलट () एक नई सूची नहीं बनाता है, यह आपूर्ति अनुक्रम पर एक रिवर्स पुनरावृत्ति बनाता है। एन्यूमरेट () की तरह, आपको इसे सूची में लपेटना होगा () वास्तव में इससे एक सूची प्राप्त करने के लिए। आप के बारे में सोच हो सकता है हल कर () है, जो करता है एक नई सूची हर बार बनाने (यह करने के लिए है, इसलिए यह यह सॉर्ट कर सकते हैं)।
ncoghlan

1
@ मौरिस क्योंकि enumerateएक पुनरावृत्त रिटर्न और reversedएक अनुक्रम की उम्मीद है। मुझे लगता है कि reversed(list(enumerate(somelist)))अगर आप स्मृति में एक अतिरिक्त सूची बनाने में कोई आपत्ति नहीं करते हैं तो आप कर सकते हैं ।
drevicko

2
यह सरणियों के लिए ओ (एन * एम) है, यह बहुत धीमी है यदि आप एक बड़ी सूची से कई आइटम निकालते हैं। इसलिए सिफारिश नहीं की।
सैम वॉटकिंस

2
@SamWatkins हाँ, यह उत्तर तब है जब आप तत्वों के एक जोड़े को एक बहुत बड़े सरणी से निकाल रहे हैं। कम स्मृति उपयोग, लेकिन यह mकई बार धीमा हो सकता है।
नवीन

52

आधिकारिक पायथन 2 ट्यूटोरियल 4.2। "स्टेटमेंट के लिए"

https://docs.python.org/2/tutorial/controlflow.html#for-statements

डॉक्स का यह हिस्सा यह स्पष्ट करता है कि:

  • आपको इसे संशोधित करने के लिए पुनरावृत्त सूची की एक प्रति बनाने की आवश्यकता है
  • इसे करने का एक तरीका स्लाइस अंकन के साथ है [:]

यदि आपको उस अनुक्रम को संशोधित करने की आवश्यकता है जो आप लूप के अंदर (उदाहरण के लिए चयनित आइटमों को डुप्लिकेट करने के लिए) कर रहे हैं, तो यह अनुशंसा की जाती है कि आप पहले एक प्रतिलिपि बनाएँ। एक अनुक्रम से अधिक का आशय स्पष्ट रूप से एक प्रति नहीं है। टुकड़ा संकेतन यह विशेष रूप से सुविधाजनक बनाता है:

>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

पायथन 2 प्रलेखन 7.3। "बयान के लिए"

https://docs.python.org/2/reference/compound_stmts.html#for

डॉक्स का यह हिस्सा एक बार फिर कहता है कि आपको एक प्रतिलिपि बनानी होगी, और एक वास्तविक निष्कासन उदाहरण देना होगा:

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

for x in a[:]:
    if x < 0: a.remove(x)

हालांकि, मैं इस कार्यान्वयन से असहमत हूं, क्योंकि मूल्य को खोजने के लिए पूरी सूची को .remove()पुनरावृत्त करना है ।

सबसे अच्छा workarounds

कोई एक:

  • खरोंच से एक नया सरणी शुरू करें, और .append()अंत में वापस जाएं : https://stackoverflow.com/a/1207460/895245

    इस बार कुशल, लेकिन कम स्थान कुशल है क्योंकि यह पुनरावृत्ति के दौरान चारों ओर सरणी की एक प्रति रखता है।

  • delएक सूचकांक के साथ उपयोग करें : https://stackoverflow.com/a/1207485/895245

    यह सरणी की प्रतिलिपि को तितर-बितर करने के बाद से अधिक स्थान कुशल है, लेकिन यह कम समय कुशल है क्योंकि CPython सूचियों को गतिशील सरणियों के साथ कार्यान्वित किया जाता है

    इसका मतलब यह है कि आइटम हटाने के लिए एक के बाद एक, जो कि O (N) है, निम्नलिखित सभी वस्तुओं को शिफ्ट करने की आवश्यकता है।

आम तौर पर आप केवल .append()डिफ़ॉल्ट रूप से तेज विकल्प के लिए जाना चाहते हैं जब तक कि स्मृति एक बड़ी चिंता का विषय न हो।

क्या अजगर बेहतर कर सकता है?

ऐसा लगता है कि इस विशेष पायथन एपीआई को बेहतर बनाया जा सकता है। उदाहरण के लिए, इसकी तुलना करें:

  • Java ListIterator :: कौन से दस्तावेज़ निकालें "यह कॉल केवल अगले या पिछले कॉल के अनुसार एक बार ही किया जा सकता है"
  • सी ++ std::vector::eraseजो एक हटाए जाने के बाद तत्व को एक वैध इंटरएटर लौटाता है

जो दोनों इसे स्पष्ट करते हैं कि आप एक सूची को पुनरावृत्त के साथ छोड़कर संशोधित नहीं कर सकते हैं, और आपको सूची को कॉपी किए बिना ऐसा करने के कुशल तरीके प्रदान करते हैं।

शायद अंतर्निहित तर्क यह है कि पायथन सूचियों को गतिशील सरणी समर्थित माना जाता है, और इसलिए किसी भी प्रकार का निष्कासन किसी भी समय अक्षम होगा, जबकि जावा में दोनों के साथ एक अच्छा इंटरफ़ेस पदानुक्रम है ArrayListऔर LinkedListकार्यान्वयन ListIterator

पायथन stdlib में या तो स्पष्ट लिंक सूची प्रकार प्रतीत नहीं होता है: पायथन लिंक्ड सूची


48

इस तरह के उदाहरण के लिए आपका सबसे अच्छा तरीका एक सूची समझ होगा

somelist = [tup for tup in somelist if determine(tup)]

ऐसे मामलों में जहां आप किसी determineफ़ंक्शन को कॉल करने की तुलना में कुछ अधिक जटिल कर रहे हैं , मैं एक नई सूची का निर्माण करना पसंद करता हूं और जैसे ही मैं जाता हूं, इसे जोड़ देता हूं। उदाहरण के लिए

newlist = []
for tup in somelist:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)
somelist = newlist

removeनीचे दिए गए किसी एक उत्तर में वर्णित के अनुसार सूची का उपयोग करने से आपका कोड थोड़ा साफ हो सकता है। आपको निश्चित रूप से यह बहुत बड़ी सूचियों के लिए नहीं करना चाहिए, क्योंकि इसमें पहली सूची को पूरी तरह से कॉपी करना शामिल है, और O(n) removeइसे हटाए जाने वाले प्रत्येक तत्व के लिए एक ऑपरेशन भी करना है, जिससे यह एक O(n^2)एल्गोरिथ्म बन जाता है।

for tup in somelist[:]:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)

37

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

somelist[:] = filter(lambda tup: not determine(tup), somelist)

या

from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))

1. सूची की समझ और जनरेटर के भाव एक शुद्ध कार्यात्मक भाषा हास्केल से उधार लिए गए हैं; वे बिल्कुल कार्यात्मक हैं filter, और अधिक पायथोनिक हैं। 2. यदि आपको lambdaउपयोग करने की आवश्यकता है mapया filter, सूची COMP या जीनएक्सप्र हमेशा बेहतर विकल्प है; mapऔर filterजब ट्रांसफॉर्म / विधेय फ़ंक्शन सी में कार्यान्वित किया जाता है, तो यह थोड़ी तेज़ी से हो सकता है और चलने योग्य तुच्छ रूप से छोटा नहीं है, लेकिन वे हमेशा धीमी होते हैं जब आपको सूची की आवश्यकता होती है lambdaकि सूची / जीनएक्सप्रो से बच सकते हैं।
शैडो रेंजर

13

मुझे एक बड़ी सूची के साथ ऐसा करने की आवश्यकता थी, और सूची को डुप्लिकेट करना महंगा लग रहा था, खासकर जब से मेरे मामले में हटाए गए आइटम की तुलना में हटाए जाने की संख्या कुछ कम होगी। मैंने यह निम्न-स्तरीय दृष्टिकोण लिया।

array = [lots of stuff]
arraySize = len(array)
i = 0
while i < arraySize:
    if someTest(array[i]):
        del array[i]
        arraySize -= 1
    else:
        i += 1

मुझे नहीं पता कि एक बड़ी सूची की नकल करने की तुलना में हटाए गए कुछ जोड़े कितने कुशल हैं। यदि आपके पास कोई अंतर्दृष्टि है, तो कृपया टिप्पणी करें।


मेरे मामले में मुझे उन 'अवांछित' तत्वों को दूसरी सूची में स्थानांतरित करने की आवश्यकता है। क्या आपके पास इस समाधान के बारे में कोई नई टिप्पणी है? मुझे यह भी लगता है कि सूची को डुप्लिकेट करने के बजाय कुछ विलोपन का उपयोग करना बेहतर है।
gustavovelascoh

यह सही उत्तर है यदि प्रदर्शन एक समस्या है (हालाँकि @Alexey के समान)। उस ने कहा, listपहली जगह में डेटा संरचना के रूप में पसंद को ध्यान से विचार किया जाना चाहिए क्योंकि सूची के बीच से हटाने से सूची की लंबाई में रैखिक समय लगता है। यदि आपको वास्तव में k- वें अनुक्रमिक आइटम तक यादृच्छिक पहुँच की आवश्यकता नहीं है, तो शायद विचार करें OrderedDict?
अधिकतम

@Gelascoh क्यों नहीं बनाया newlist = [], और फिर newlist.append(array[i])पहले del array[i]?
अधिकतम

2
ध्यान दें कि यह संभावित समय अक्षम है: यदि list()एक लिंक की गई सूची है, तो यादृच्छिक पहुंच महंगी है, अगर list()एक सरणी है, तो हटाए गए महंगे हैं क्योंकि उन्हें निम्नलिखित सभी तत्वों को आगे बढ़ाने की आवश्यकता है। एक सभ्य पुनरावृत्ति लिंक्ड सूची कार्यान्वयन के लिए चीजों को अच्छा बना सकता है। यह हालांकि अंतरिक्ष कुशल हो सकता है।
सिरो सेंटिल्ली 冠状 iro iro 法轮功

10

यदि वर्तमान सूची आइटम वांछित मानदंडों को पूरा करता है तो यह भी एक नई सूची बनाने के लिए स्मार्ट हो सकता है।

इसलिए:

for item in originalList:
   if (item != badValue):
        newList.append(item)

और नई सूची के नाम के साथ पूरी परियोजना को फिर से कोड करने से बचने के लिए:

originalList[:] = newList

ध्यान दें, पायथन प्रलेखन से:

copy.copy (x) x की उथली प्रति लौटाएं।

copy.deepcopy (x) x की गहरी प्रति लौटाएं।


3
यह कोई नई जानकारी नहीं जोड़ता है जो पहले स्वीकार किए गए उत्तर वर्षों में नहीं थी।
मार्क अमेरी

2
यह एक समस्या @MarkAmery को देखने के लिए सरल और सिर्फ एक और तरीका है। यह उन लोगों के लिए कम संघटित है जो संकुचित कोडिंग सिंटैक्स को पसंद नहीं करते हैं।
ntk4

9

यह उत्तर मूल रूप से एक प्रश्न के उत्तर में लिखा गया था, जिसे तब से डुप्लिकेट के रूप में चिह्नित किया गया है: अजगर पर सूची से निर्देशांक हटाते हुए

आपके कोड में दो समस्याएं हैं:

1) हटाने () का उपयोग करते समय, आप पूर्णांक को हटाने का प्रयास करते हैं, जबकि आपको टपल को निकालने की आवश्यकता होती है।

2) लूप के लिए आपकी सूची में आइटम छोड़ देंगे।

जब हम आपके कोड को निष्पादित करते हैं तो क्या होता है:

>>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
>>> for (a,b) in L1:
...   if a < 0 or b < 0:
...     L1.remove(a,b)
... 
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: remove() takes exactly one argument (2 given)

पहली समस्या यह है कि आप हटाने के लिए 'a' और 'b' दोनों पास कर रहे हैं (), लेकिन remove () केवल एक ही तर्क को स्वीकार करता है। तो हम आपकी सूची के साथ ठीक से काम करने के लिए कैसे निकाल सकते हैं ()? हमें यह पता लगाने की आवश्यकता है कि आपकी सूची का प्रत्येक तत्व क्या है। इस मामले में, प्रत्येक एक टपल है। इसे देखने के लिए, आइए सूची के एक तत्व तक पहुँचें (अनुक्रमण 0 से शुरू होता है):

>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>

अहा! एल 1 का प्रत्येक तत्व वास्तव में एक टपल है। इसलिए इसे हटाने के लिए हमें पास होने की जरूरत है ()। अजगर में ट्यूपल्स बहुत आसान हैं, वे बस कोष्ठक में मूल्यों को संलग्न करके बनाए जाते हैं। "ए, बी" एक टपल नहीं है, लेकिन "(ए, बी)" एक टपल है। इसलिए हम आपके कोड को संशोधित करते हैं और इसे फिर से चलाते हैं:

# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))

यह कोड बिना किसी त्रुटि के चलता है, लेकिन आइए इसकी आउटपुट सूची को देखें:

L1 is now: [(1, 2), (5, 6), (1, -2)]

आपकी सूची में अभी भी (1, -2) क्यों है? यह सूची को संशोधित करता है जबकि एक लूप का उपयोग करने के लिए यह विशेष देखभाल के बिना एक बहुत बुरा विचार है। सूची में बने रहने का कारण (1, -2) यह है कि सूची के भीतर प्रत्येक आइटम के स्थान लूप के पुनरावृत्तियों के बीच बदल गए। आइए देखें कि क्या होता है अगर हम उपरोक्त कोड को एक लंबी सूची खिलाते हैं:

L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
### Outputs:
L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

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

सबसे सहज समाधान सूची की नकल करना है, फिर मूल सूची पर पुनरावृत्ति करना और केवल प्रतिलिपि को संशोधित करना है। आप ऐसा करने की कोशिश कर सकते हैं:

L2 = L1
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
print L2 is L1
del L1
L1 = L2; del L2
print ("L1 is now: ", L1)

हालाँकि, आउटपुट पहले के समान होगा:

'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

ऐसा इसलिए है क्योंकि जब हमने L2 बनाया था, तो अजगर ने वास्तव में एक नई वस्तु नहीं बनाई थी। इसके बजाय, उसने L2 को L1 के समान ऑब्जेक्ट के लिए संदर्भित किया। हम इसे 'is ’के साथ सत्यापित कर सकते हैं जो केवल" बराबर "(==) से अलग है।

>>> L2=L1
>>> L1 is L2
True

हम copy.copy () का उपयोग करके एक सच्ची प्रतिलिपि बना सकते हैं। फिर सब कुछ उम्मीद के मुताबिक काम करता है:

import copy
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
L2 = copy.copy(L1)
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
del L1
L1 = L2; del L2
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

अंत में, L1 की पूरी तरह से नई प्रतिलिपि बनाने की तुलना में एक क्लीनर समाधान है। उलटा () फ़ंक्शन:

L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
for (a,b) in reversed(L1):
    if a < 0 or b < 0 :
        L1.remove((a,b))
print ("L1 is now: ", L1)
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

दुर्भाग्य से, मैं पर्याप्त रूप से वर्णन नहीं कर सकता कि कैसे उलट () काम करता है। जब कोई सूची पास हो जाती है, तो वह 'listreverseiterator' ऑब्जेक्ट देता है। व्यावहारिक उद्देश्यों के लिए, आप इसके तर्क की उलटी प्रतिलिपि बनाने के रूप में सोच सकते हैं। यह वह उपाय है जो मैं सुझाता हूं।


4

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

inlist = [{'field1':10, 'field2':20}, {'field1':30, 'field2':15}]    
for idx, i in enumerate(inlist):
    do some stuff with i['field1']
    if somecondition:
        xlist.append(idx)
for i in reversed(xlist): del inlist[i]

enumerateआपको एक ही बार में आइटम और इंडेक्स तक पहुंच प्रदान करता है। reversedऐसा इसलिए है कि जिन सूचकांकों को आप बाद में हटाने जा रहे हैं, वे आप पर नहीं बदलते हैं।


सूचकांक को उस मामले में अधिक प्रासंगिक क्यों माना जा रहा है जहां आपके पास किसी अन्य प्रकार की सूची की तुलना में dicts की सूची है? जहाँ तक मैं बता सकता हूँ, इसका कोई मतलब नहीं है।
मार्क अमेरी


4

यहां अधिकांश उत्तर चाहते हैं कि आप सूची की एक प्रति बनाएं। मेरे पास एक उपयोग का मामला था जहां सूची काफी लंबी (110K आइटम) थी और इसके बजाय सूची को कम रखने के लिए यह अधिक स्मार्ट था।

सबसे पहले आपको लूप के साथ फॉरच लूप को बदलना होगा ,

i = 0
while i < len(somelist):
    if determine(somelist[i]):
         del somelist[i]
    else:
        i += 1

iयदि किसी पुराने आइटम को हटा दिया जाता है, तो उस मूल्य को बदल नहीं दिया जाता क्योंकि आप ब्लॉक में नए आइटम का मूल्य प्राप्त करना चाहते हैं।


3

आप उल्टे लूपिंग की कोशिश कर सकते हैं ताकि some_list के लिए आप कुछ ऐसा करें:

list_len = len(some_list)
for i in range(list_len):
    reverse_i = list_len - 1 - i
    cur = some_list[reverse_i]

    # some logic with cur element

    if some_condition:
        some_list.pop(reverse_i)

इस तरह से सूचकांक संरेखित होता है और सूची अपडेट से पीड़ित नहीं होता है (चाहे आप कर्व तत्व पॉप करते हों या नहीं)।


लूपिंग ओवर reversed(list(enumerate(some_list)))खुद को अनुक्रमित करने की तुलना में सरल होगा।
मार्क अमेरी

@ मार्की को नहीं लगता कि आप सूची को इस तरह बदल सकते हैं।
क्यूईकेग

3

एक संभव समाधान, उपयोगी यदि आप न केवल कुछ चीजों को हटाना चाहते हैं, बल्कि एक ही लूप में सभी तत्वों के साथ कुछ करना चाहते हैं:

alist = ['good', 'bad', 'good', 'bad', 'good']
i = 0
for x in alist[:]:
    if x == 'bad':
        alist.pop(i)
        i -= 1
    # do something cool with x or just print x
    print(x)
    i += 1

आपको वास्तव में सिर्फ समझ का उपयोग करना चाहिए। वे समझने में बहुत आसान हैं।
बीफस्टर

क्या होगा अगर मैं badचीजों को हटाना चाहता हूं , इसके साथ कुछ करना है और goodएक लूप में चीजों के साथ भी कुछ करना है ?
एलेक्सी

1
वास्तव में, मुझे महसूस हुआ कि यहाँ कुछ चतुराई है कि आप सूची को एक खुले स्लाइस ( alist[:]) के साथ बनाते हैं और जब से आप कुछ फैंसी कर रहे होंगे, वास्तव में इसका उपयोग मामला है। अच्छा रिवीजन अच्छा है। मेरा उत्थान करो।
बीफस्टर

2

मुझे कुछ समान करने की आवश्यकता थी और मेरे मामले में समस्या स्मृति थी - मुझे एक सूची के भीतर कई डेटासेट ऑब्जेक्ट्स को मर्ज करने की आवश्यकता थी, उनके साथ कुछ सामान करने के बाद, एक नई वस्तु के रूप में, और प्रत्येक प्रविष्टि से छुटकारा पाने के लिए मुझे इसमें विलय करना था। उन सभी को डुप्लिकेट करने और स्मृति को उड़ाने से बचें। मेरे मामले में एक सूची के बजाय एक शब्दकोश में वस्तुओं का होना ठीक काम करता है:

`` `

k = range(5)
v = ['a','b','c','d','e']
d = {key:val for key,val in zip(k, v)}

print d
for i in range(5):
    print d[i]
    d.pop(i)
print d

`` `


2

TLDR:

मैंने एक पुस्तकालय लिखा है जो आपको ऐसा करने की अनुमति देता है:

from fluidIter import FluidIterable
fSomeList = FluidIterable(someList)  
for tup in fSomeList:
    if determine(tup):
        # remove 'tup' without "breaking" the iteration
        fSomeList.remove(tup)
        # tup has also been removed from 'someList'
        # as well as 'fSomeList'

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

न केवल सूचियों के सभी परिवर्तनशील अनुक्रमों पर काम करना चाहिए।


पूर्ण उत्तर:

संपादित करें: इस उत्तर में अंतिम कोड उदाहरण इस बात के लिए उपयोग का मामला देता है कि आप कभी-कभी सूची बोध का उपयोग करने के बजाय किसी सूची को संशोधित करना चाहते हैं। उत्तरों का पहला भाग ट्यूटोरियल के रूप में कार्य करता है कि किसी सरणी को किस प्रकार संशोधित किया जा सकता है।

समाधान से पर निम्न प्रकार इस प्रेषक के उत्तर (संबंधित प्रश्न के लिए) से आता है। जो यह बताता है कि संशोधित किए गए सूची के माध्यम से पुनरावृत्ति करते समय सरणी सूचकांक कैसे अपडेट किया जाता है। नीचे दिए गए समाधान को सूची सूचकांक को सही ढंग से ट्रैक करने के लिए डिज़ाइन किया गया है, भले ही सूची संशोधित हो।

यहांfluidIter.py से डाउनलोड करें https://github.com/alanbacon/FluidIterator , यह सिर्फ एक ही फाइल है ताकि गिट स्थापित करने की कोई आवश्यकता नहीं है। कोई इंस्टॉलर नहीं है, इसलिए आपको यह सुनिश्चित करने की आवश्यकता होगी कि फ़ाइल आपके स्वयं के लिए अजगर पथ में है। कोड को पायथन 3 के लिए लिखा गया है और यह अजगर 2 पर अनुपलब्ध है।

from fluidIter import FluidIterable
l = [0,1,2,3,4,5,6,7,8]  
fluidL = FluidIterable(l)                       
for i in fluidL:
    print('initial state of list on this iteration: ' + str(fluidL)) 
    print('current iteration value: ' + str(i))
    print('popped value: ' + str(fluidL.pop(2)))
    print(' ')

print('Final List Value: ' + str(l))

यह निम्नलिखित उत्पादन का उत्पादन करेगा:

initial state of list on this iteration: [0, 1, 2, 3, 4, 5, 6, 7, 8]
current iteration value: 0
popped value: 2

initial state of list on this iteration: [0, 1, 3, 4, 5, 6, 7, 8]
current iteration value: 1
popped value: 3

initial state of list on this iteration: [0, 1, 4, 5, 6, 7, 8]
current iteration value: 4
popped value: 4

initial state of list on this iteration: [0, 1, 5, 6, 7, 8]
current iteration value: 5
popped value: 5

initial state of list on this iteration: [0, 1, 6, 7, 8]
current iteration value: 6
popped value: 6

initial state of list on this iteration: [0, 1, 7, 8]
current iteration value: 7
popped value: 7

initial state of list on this iteration: [0, 1, 8]
current iteration value: 8
popped value: 8

Final List Value: [0, 1]

ऊपर हमने popद्रव सूची वस्तु पर विधि का उपयोग किया है । अन्य आम iterable तरीकों में भी इस तरह के रूप में लागू किया जाता है del fluidL[i], .remove, .insert, .append, .extend। सूची को स्लाइस ( sortऔर) का उपयोग करके भी संशोधित किया जा सकता हैreverse विधियों को लागू नहीं किया गया है)।

एकमात्र शर्त यह है कि आपको सूची को केवल उसी स्थान पर संशोधित करना होगा, यदि किसी भी बिंदु पर fluidLया किसी lभिन्न सूची पर पुन: असाइन किया गया था, तो ऑब्जेक्ट काम नहीं करेगा। मूल fluidLवस्तु अभी भी लूप के लिए उपयोग की जाएगी, लेकिन हमारे द्वारा संशोधित करने की गुंजाइश से बाहर हो जाएगी।

अर्थात

fluidL[2] = 'a'   # is OK
fluidL = [0, 1, 'a', 3, 4, 5, 6, 7, 8]  # is not OK

यदि हम सूची के वर्तमान इंडेक्स मान को एक्सेस करना चाहते हैं तो हम एन्युमरेट का उपयोग नहीं कर सकते हैं, क्योंकि यह केवल यह बताता है कि लूप के लिए कितनी बार चला है। इसके बजाय हम सीधे itter ऑब्जेक्ट का उपयोग करेंगे।

fluidArr = FluidIterable([0,1,2,3])
# get iterator first so can query the current index
fluidArrIter = fluidArr.__iter__()
for i, v in enumerate(fluidArrIter):
    print('enum: ', i)
    print('current val: ', v)
    print('current ind: ', fluidArrIter.currentIndex)
    print(fluidArr)
    fluidArr.insert(0,'a')
    print(' ')

print('Final List Value: ' + str(fluidArr))

यह निम्नलिखित उत्पादन करेगा:

enum:  0
current val:  0
current ind:  0
[0, 1, 2, 3]

enum:  1
current val:  1
current ind:  2
['a', 0, 1, 2, 3]

enum:  2
current val:  2
current ind:  4
['a', 'a', 0, 1, 2, 3]

enum:  3
current val:  3
current ind:  6
['a', 'a', 'a', 0, 1, 2, 3]

Final List Value: ['a', 'a', 'a', 'a', 0, 1, 2, 3]

FluidIterableवर्ग सिर्फ मूल सूची वस्तु के लिए एक आवरण प्रदान करता है। मूल वस्तु को इस तरह द्रव पदार्थ की संपत्ति के रूप में एक्सेस किया जा सकता है:

originalList = fluidArr.fixedIterable

अधिक उदाहरण / परीक्षण if __name__ is "__main__":अनुभाग में सबसे नीचे पाए जा सकते हैं fluidIter.py। ये देखने लायक हैं क्योंकि वे बताते हैं कि विभिन्न स्थितियों में क्या होता है। जैसे: एक स्लाइस का उपयोग करके सूची के एक बड़े हिस्से को बदलना। या (और संशोधन) लूप के लिए नेस्टेड में एक ही पुनरावृत्ति का उपयोग करना।

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


संपादित करें: जैसा कि टिप्पणियों में उल्लेख किया गया है, यह उत्तर वास्तव में एक समस्या पेश नहीं करता है जिसके लिए यह दृष्टिकोण एक समाधान प्रदान करता है। मैं उसे यहाँ संबोधित करने की कोशिश करूँगा:

सूची की समझ एक नई सूची उत्पन्न करने का एक तरीका प्रदान करती है लेकिन ये दृष्टिकोण सूची के वर्तमान स्थिति के बजाय अलगाव में प्रत्येक तत्व को देखते हैं।

अर्थात

newList = [i for i in oldList if testFunc(i)]

लेकिन क्या होगा अगर पहले testFuncसे newListही जोड़े गए तत्वों पर निर्भर करता है ? या तत्व अभी भी अंदर हैंoldList उसमें अगले जोड़ा जा सकता है? अभी भी एक सूची समझ का उपयोग करने का एक तरीका हो सकता है, लेकिन यह लालित्य खोना शुरू हो जाएगा, और मेरे लिए जगह में एक सूची को संशोधित करना आसान लगता है।

नीचे दिया गया कोड एल्गोरिथ्म का एक उदाहरण है जो उपरोक्त समस्या से ग्रस्त है। एल्गोरिथ्म एक सूची को कम करेगा ताकि कोई भी तत्व किसी भी अन्य तत्व का गुणक न हो।

randInts = [70, 20, 61, 80, 54, 18, 7, 18, 55, 9]
fRandInts = FluidIterable(randInts)
fRandIntsIter = fRandInts.__iter__()
# for each value in the list (outer loop)
# test against every other value in the list (inner loop)
for i in fRandIntsIter:
    print(' ')
    print('outer val: ', i)
    innerIntsIter = fRandInts.__iter__()
    for j in innerIntsIter:
        innerIndex = innerIntsIter.currentIndex
        # skip the element that the outloop is currently on
        # because we don't want to test a value against itself
        if not innerIndex == fRandIntsIter.currentIndex:
            # if the test element, j, is a multiple 
            # of the reference element, i, then remove 'j'
            if j%i == 0:
                print('remove val: ', j)
                # remove element in place, without breaking the
                # iteration of either loop
                del fRandInts[innerIndex]
            # end if multiple, then remove
        # end if not the same value as outer loop
    # end inner loop
# end outerloop

print('')
print('final list: ', randInts)

आउटपुट और अंतिम कम सूची नीचे दी गई है

outer val:  70

outer val:  20
remove val:  80

outer val:  61

outer val:  54

outer val:  18
remove val:  54
remove val:  18

outer val:  7
remove val:  70

outer val:  55

outer val:  9
remove val:  18

final list:  [20, 61, 7, 55, 9]

यह बताना मुश्किल है कि क्या यह अधिक इंजीनियर है क्योंकि यह स्पष्ट नहीं है कि यह किस समस्या को हल करने की कोशिश कर रहा है; इस दृष्टिकोण का उपयोग करने वाले तत्वों को हटाने से क्या हासिल होता some_list[:] = [x for x in some_list if not some_condition(x)]है? इसके जवाब के बिना, किसी को भी यह क्यों मानना ​​चाहिए कि टाइपो और कमेंट-आउट कोड के साथ आपकी 600-लाइन लाइब्रेरी को डाउनलोड करना और उपयोग करना वन-लाइनर की तुलना में उनकी समस्या का बेहतर समाधान है? -1।
मार्क अमेरी

@MarkAmery। इस बात का मुख्य उपयोग मामला तब होता है जब यह निर्धारित करने की कोशिश की जाती है कि क्या किसी वस्तु को केवल आइटम के आधार पर नहीं हटाया जाना चाहिए (या जोड़ा या स्थानांतरित किया गया), लेकिन सूची में किसी अन्य आइटम की स्थिति या सूची के रूप में स्थिति पूरा का पूरा। उदाहरण के लिए, सूची बोध के साथ यह संभव नहीं है कि कुछ ऐसा लिखा जाए some_list[:] = [x for x in some_list if not some_condition(y)]जहां yसे अलग सूची तत्व हो x। न ही लिखना संभव होगा some_list[:] = [x for x in some_list if not some_condition(intermediateStateOf_some_list)]
अनुगमन

2

सबसे कारगर तरीका सूची समझ, कई लोग अपनी मामले दिखाने के लिए, ज़ाहिर है, यह भी एक अच्छा तरीका है एक पाने के लिए है iteratorके माध्यम से filter

Filterएक समारोह और एक अनुक्रम प्राप्त करता है। Filterबदले में प्रत्येक तत्व को पारित फ़ंक्शन लागू करता है, और फिर यह निर्णय लेता है कि फ़ंक्शन वापसी मान है Trueया नहीं, इस आधार पर तत्व को बनाए रखना या त्यागना है या नहीं False

एक उदाहरण है (टपल में अंतर पाएं):

list(filter(lambda x:x%2==1, (1, 2, 4, 5, 6, 9, 10, 15)))  
# result: [1, 5, 9, 15]

सावधानी: आप पुनरावृत्तियों को भी नहीं संभाल सकते। Iterators कभी-कभी अनुक्रम से बेहतर होते हैं।


2

लूप के लिए सूचकांक के माध्यम से पुनरावृति होगी ।।

विचार करें कि आपके पास एक सूची है,

[5, 7, 13, 29, 65, 91]

आपके पास सूची चर का उपयोग किया जाता है lis। और आप हटाने के लिए उसी का उपयोग कर रहे हैं ..

आपका चर

lis = [5, 7, 13, 29, 35, 65, 91]
       0  1   2   3   4   5   6

5 वीं यात्रा के दौरान,

आपकी संख्या 35 एक अभाज्य नहीं थी इसलिए आपने इसे एक सूची से हटा दिया।

lis.remove(y)

और फिर अगले मूल्य (65) पिछले सूचकांक पर चलते हैं।

lis = [5, 7, 13, 29, 65, 91]
       0  1   2   3   4   5

तो 4 पुनरावृत्ति किया सूचक 5 पर चले गए ..

यही कारण है कि पिछले सूचकांक में स्थानांतरित होने के बाद आपका लूप नॉट 65 को कवर करता है।

इसलिए आपको सूची को किसी अन्य चर में नहीं देखना चाहिए जो प्रतिलिपि के बजाय अभी भी मूल संदर्भ में है।

ite = lis #dont do it will reference instead copy

इसलिए सूची का उपयोग करते हुए प्रतिलिपि बनाएँ list[::]

अब आप इसे देंगे,

[5, 7, 13, 29]

समस्या यह है कि क्या आपको पुनरावृत्ति के दौरान एक सूची से मान निकाल दिया जाता है तो आपकी सूची सूचकांक ध्वस्त हो जाएगा।

इसलिए आप इसके बजाय समझ की कोशिश कर सकते हैं।

जो सभी चलने योग्य का समर्थन करता है जैसे, सूची, टपल, तानाशाही, स्ट्रिंग आदि


इससे मुझे यह समझने में मदद मिली कि मेरा कोड क्यों विफल हो रहा था।
वाहिद सादिक

2

यदि आप पुनरावृत्ति करते समय किसी सूची से तत्वों को हटाना चाहते हैं, तो थोड़ी देर के लूप का उपयोग करें ताकि आप अपने विलोपन के बाद वर्तमान सूचकांक और अंत सूचकांक को बदल सकें।

उदाहरण:

i = 0
length = len(list1)

while i < length:
    if condition:
        list1.remove(list1[i])
        i -= 1
        length -= 1

    i += 1

1

अन्य उत्तर सही हैं कि आमतौर पर एक सूची से हटाना एक बुरा विचार है जिसे आप पुनरावृत्त कर रहे हैं। उल्टा पुनरावृत्ति नुकसान से बचा जाता है, लेकिन कोड का पालन करना बहुत अधिक कठिन है जो ऐसा करता है, इसलिए आमतौर पर आप सूची बोध का उपयोग करके बेहतर होते हैं या filter

हालाँकि, एक ऐसा मामला है जहां तत्वों को उस अनुक्रम से निकालना सुरक्षित है, जो आप पुनरावृत्त कर रहे हैं: यदि आप केवल एक आइटम निकाल रहे हैं, जब आप पुनरावृत्ति कर रहे हैं। यह एक returnया एक का उपयोग करके सुनिश्चित किया जा सकता है break। उदाहरण के लिए:

for i, item in enumerate(lst):
    if item % 4 == 0:
        foo(item)
        del lst[i]
        break

जब आप किसी सूची में पहले आइटम पर साइड इफेक्ट के साथ कुछ ऑपरेशन कर रहे होते हैं तो कुछ शर्त पूरी करते हैं और फिर उस आइटम को सूची से तुरंत हटा देते हैं।


1

मैं आपकी समस्या को हल करने के लिए तीन दृष्टिकोणों के बारे में सोच सकता हूं। एक उदाहरण के रूप में, मैं टुपल्स की एक यादृच्छिक सूची बनाऊंगा somelist = [(1,2,3), (4,5,6), (3,6,6), (7,8,9), (15,0,0), (10,11,12)]। मेरे द्वारा चुनी गई शर्त है sum of elements of a tuple = 15। अंतिम सूची में हमारे पास केवल वे ट्यूपल होंगे जिनकी राशि 15 के बराबर नहीं है।

मैंने जो चुना है वह एक बेतरतीब ढंग से चुना गया उदाहरण है। टफल्स की सूची और मेरे द्वारा चुनी गई स्थिति को बदलने के लिए स्वतंत्र महसूस करें

विधि 1.> आपके द्वारा सुझाए गए ढांचे का उपयोग करें (जहां एक लूप के अंदर कोड में भरता है)। मैं एक छोटे कोड का उपयोग करता हूं, delजो टपल को हटाने के लिए कहा जाता है। हालांकि, यह विधि एक टपल को याद करेगी (जो उक्त स्थिति को संतुष्ट करती है) यदि दो लगातार टपल दिए गए स्थिति को पूरा करते हैं।

for tup in somelist:
    if ( sum(tup)==15 ): 
        del somelist[somelist.index(tup)]

print somelist
>>> [(1, 2, 3), (3, 6, 6), (7, 8, 9), (10, 11, 12)]

विधि 2.> एक नई सूची का निर्माण करें जिसमें ऐसे तत्व (ट्यूपल्स) हों जहाँ दी गई शर्त पूरी नहीं की गई है (यह सूची के तत्वों को हटाने के समान है जहाँ दी गई शर्त पूरी होती है)। इसके लिए कोड निम्नलिखित है:

newlist1 = [somelist[tup] for tup in range(len(somelist)) if(sum(somelist[tup])!=15)]

print newlist1
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

विधि 3.> उन सूचकांकों का पता लगाएं, जहां दी गई स्थिति पूरी हुई है, और फिर उन सूचकांकों के अनुरूप हटाने वाले तत्वों (टुपल्स) का उपयोग करें। इसके लिए कोड निम्नलिखित है।

indices = [i for i in range(len(somelist)) if(sum(somelist[i])==15)]
newlist2 = [tup for j, tup in enumerate(somelist) if j not in indices]

print newlist2
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

विधि 1 और विधि 2 विधि 3 की तुलना में तेज़ हैं । Method1 और Method3 Method1 की तुलना में अधिक कुशल हैं। मुझे मेथड 2 पसंद है । उपर्युक्त उदाहरण के लिए,time(method1) : time(method2) : time(method3) = 1 : 1 : 1.7


0

किसी भी चीज के लिए जो वास्तव में बड़ी होने की क्षमता है, मैं निम्नलिखित का उपयोग करता हूं।

import numpy as np

orig_list = np.array([1, 2, 3, 4, 5, 100, 8, 13])

remove_me = [100, 1]

cleaned = np.delete(orig_list, remove_me)
print(cleaned)

यह किसी भी चीज की तुलना में काफी तेज होना चाहिए।


मैंने जो मापा, उसमें से 20 से अधिक तत्वों की सूचियों के लिए NumPy तेज़ होना शुरू हो गया, और 1000 तत्वों और अधिक की बड़ी सूचियों के लिए 12x तेज़ फ़िल्टरिंग तक पहुँच गया।
जार्ज

0

कुछ स्थितियों में, जहाँ आप किसी सूची को एक समय में एक आइटम को फ़िल्टर करने से अधिक कर रहे हैं, आप चाहते हैं कि आपकी पुनरावृति पुनरावृत्ति करते समय बदल जाए।

यहां एक उदाहरण है जहां पहले से सूची की नकल करना गलत है, उल्टा चलना असंभव है और एक सूची समझ भी एक विकल्प नहीं है।

""" Sieve of Eratosthenes """

def generate_primes(n):
    """ Generates all primes less than n. """
    primes = list(range(2,n))
    idx = 0
    while idx < len(primes):
        p = primes[idx]
        for multiple in range(p+p, n, p):
            try:
                primes.remove(multiple)
            except ValueError:
                pass #EAFP
        idx += 1
        yield p

0

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

for i in li:
    i = None

for elem in li:
    if elem is None:
        continue

इस तरह, आपको सूची की प्रतिलिपि बनाने की आवश्यकता नहीं है और इसे समझना आसान है।


-1

संख्या की एक सूची को छोड़ दें और आप उन सभी को हटाना चाहते हैं जो 3 से विभाज्य हैं,

list_number =[i for i in range(100)]

उपयोग करते हुए list comprehension, यह एक नई सूची बनाएगा और नई मेमोरी स्पेस बनाएगा

new_list =[i for i in list_number if i%3!=0]

lambda filterफ़ंक्शन का उपयोग करते हुए, यह परिणामी नई सूची बनाएगा और मेमरी स्थान का उपभोग करेगा

new_list = list(filter(lambda x:x%3!=0, list_number))

नई सूची के लिए मेमोरी स्पेस का उपभोग किए बिना और मौजूदा सूची को संशोधित करें

for index, value in enumerate(list_number):
    if list_number[index]%3==0:
        list_number.remove(value)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.