यदि किसी सूची में कोई आइटम मौजूद है तो उसे कैसे हटाएं?


258

मैं के new_tagसाथ self.response.get("new_tag")और के साथ selected_tagsचेकबॉक्स फ़ील्ड से एक प्रपत्र पाठ फ़ील्ड से प्राप्त कर रहा हूं

self.response.get_all("selected_tags")

मैं उन्हें इस तरह से जोड़ती हूं:

tag_string = new_tag
new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)

( f1.striplistएक फ़ंक्शन है जो सूची में स्ट्रिंग्स के अंदर सफेद रिक्त स्थान को स्ट्रिप्स करता है।)

लेकिन उस मामले में जो tag_listखाली है (कोई नया टैग दर्ज नहीं किया गया है) लेकिन कुछ हैं selected_tags, new_tag_listजिसमें एक खाली स्ट्रिंग है " "

उदाहरण के लिए, से logging.info:

new_tag
selected_tags[u'Hello', u'Cool', u'Glam']
new_tag_list[u'', u'Hello', u'Cool', u'Glam']

मैं खाली स्ट्रिंग से कैसे छुटकारा पाऊं?

यदि सूची में कोई खाली स्ट्रिंग है:

>>> s = [u'', u'Hello', u'Cool', u'Glam']
>>> i = s.index("")
>>> del s[i]
>>> s
[u'Hello', u'Cool', u'Glam']

लेकिन अगर कोई खाली स्ट्रिंग नहीं है:

>>> s = [u'Hello', u'Cool', u'Glam']
>>> if s.index(""):
        i = s.index("")
        del s[i]
    else:
        print "new_tag_list has no empty string"

लेकिन यह देता है:

Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    if new_tag_list.index(""):
        ValueError: list.index(x): x not in list

ऐसा क्यों होता है, और मैं इसके आसपास कैसे काम करूं?

जवाबों:


718

1) लगभग-अंग्रेजी शैली:

inऑपरेटर का उपयोग करके उपस्थिति के लिए परीक्षण करें , फिर removeविधि लागू करें ।

if thing in some_list: some_list.remove(thing)

removeविधि का केवल पहली घटना निकाल देंगे thing, सभी घटनाओं आप उपयोग कर सकते हैं हटाने के लिए whileकी बजाय if

while thing in some_list: some_list.remove(thing)    
  • काफी सरल, शायद मेरी पसंद। छोटी सूचियों के लिए (एक-लाइनर्स का विरोध नहीं किया जा सकता)

2) बतख-टाइप , ईएएफपी शैली:

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

try:
    some_list.remove(thing)
except ValueError:
    pass # or scream: thing not in some_list!
except AttributeError:
    call_security("some_list not quacking like a list!")

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

यदि आप किसी चीज़ के होने की उम्मीद करते हैं:

while True:
    try:
        some_list.remove(thing)
    except ValueError:
        break
  • इस विशिष्ट उपयोग के मामले के लिए एक छोटी सी क्रिया, लेकिन पायथन में बहुत ही मुहावरेदार।
  • यह # 1 से बेहतर प्रदर्शन करता है
  • PEP 463 ने सरल उपयोग के लिए प्रयास / सिवाय एक छोटे वाक्यविन्यास का प्रस्ताव रखा जो यहां काम आएगा, लेकिन यह स्वीकृत नहीं था।

हालाँकि, प्रसंग के दमन () के संदर्भ में (अजगर 3.4 में पेश) उपरोक्त कोड इसके लिए सरल हो सकता है:

with suppress(ValueError, AttributeError):
    some_list.remove(thing)

फिर, यदि आप किसी चीज़ की कई घटनाओं की अपेक्षा करते हैं:

with suppress(ValueError):
    while True:
        some_list.remove(thing)

3) कार्यात्मक शैली:

लगभग 1993, अजगर मिला lambda, reduce(), filter()और map(), एक के सौजन्य से लिस्प हैकर जो उन्हें याद किया और प्रस्तुत काम कर पैच *। आप filterसूची से तत्वों को निकालने के लिए उपयोग कर सकते हैं :

is_not_thing = lambda x: x is not thing
cleaned_list = filter(is_not_thing, some_list)

एक शॉर्टकट है जो आपके मामले के लिए उपयोगी हो सकता है: यदि आप खाली आइटम (वास्तव में आइटम bool(item) == False, जैसे None, शून्य, खाली स्ट्रिंग या अन्य खाली संग्रह) को फ़िल्टर करना चाहते हैं , तो आप पहले तर्क के रूप में कोई भी पास नहीं कर सकते:

cleaned_list = filter(None, some_list)
  • [अद्यतन] : पायथन 2.x में, (या यदि पहला तर्क है ) के filter(function, iterable)बराबर हुआ करता था ; पायथन 3.x में, यह अब के बराबर है । सूक्ष्म अंतर यह है कि किसी सूची को वापस करने के लिए उपयोग किए जाने वाले फ़िल्टर का उपयोग किया जाता है, अब यह एक जनरेटर अभिव्यक्ति की तरह काम करता है - यह ठीक है यदि आप केवल साफ की गई सूची पर पुनरावृत्ति कर रहे हैं और इसे छोड़ रहे हैं, लेकिन अगर आपको वास्तव में सूची की आवश्यकता है, तो आपको कॉल को संलग्न करना होगा कंस्ट्रक्टर के साथ ।[item for item in iterable if function(item)][item for item in iterable if item]None(item for item in iterable if function(item))filter()list()
  • * इन लिस्फी स्वाद वाले निर्माणों को पायथन में थोड़ा विदेशी माना जाता है। 2005 के आसपास, गुइडो यहां तक ​​कि छोड़ने के बारे में बात कर रहे थेfilter - साथियों के साथ mapऔर reduce(वे अभी तक नहीं गए हैं, लेकिन फंक्शनलबूल मॉड्यूल reduceमें ले जाया गया था , जो एक नज़र के लायक है यदि आप उच्च आदेश कार्यों को पसंद करते हैं )।

4) गणितीय शैली:

PEP 202 द्वारा संस्करण 2.0 में पेश किए जाने के बाद से सूची समझ पायथन में सूची हेरफेर के लिए पसंदीदा शैली बन गई । इसके पीछे तर्क यह है कि सूची comprehensions स्थितियों में सूची बनाने के लिए जहां एक और अधिक संक्षिप्त तरीके प्रदान करना है map()और filter()और / या नेस्टेड छोरों वर्तमान में इस्तेमाल किया जाएगा।

cleaned_list = [ x for x in some_list if x is not thing ]

पीईपी 289 द्वारा जेनरेटर एक्सप्रेशंस को 2.4 संस्करण में पेश किया गया था । एक जनरेटर अभिव्यक्ति उन स्थितियों के लिए बेहतर है जहां आपको स्मृति में पूरी सूची बनाने की आवश्यकता नहीं है (या चाहते हैं) - जैसे कि जब आप तत्वों को एक बार में एक से अधिक बनाना चाहते हैं। यदि आप सूची में केवल पुनरावृत्ति कर रहे हैं, तो आप एक जनरेटर के अभिव्यक्ति को एक आलसी मूल्यांकन सूची समझ के रूप में समझ सकते हैं:

for item in (x for x in some_list if x is not thing):
    do_your_thing_with(item)

टिप्पणियाँ

  1. आप !=इसके बजाय असमानता ऑपरेटर का उपयोग करना चाहते हैं is not( अंतर महत्वपूर्ण है )
  2. सूची की प्रतिलिपि बनाने के तरीकों के आलोचकों के लिए: लोकप्रिय धारणा के विपरीत, जनरेटर अभिव्यक्तियाँ हमेशा सूची की समझ से अधिक कुशल नहीं होती हैं - शिकायत करने से पहले कृपया प्रोफ़ाइल करें

3
क्या मैं सुझाव दे सकता हूं कि (2) एट्रिब्यूट हैंडलिंग को छोड़ दें? यह विचलित कर रहा है और अन्य वर्गों (या उसी खंड के अन्य भागों) में संभाला नहीं गया है। इससे भी बदतर, किसी को उस कोड की प्रतिलिपि हो सकती है जो यह महसूस नहीं कर रहे हैं कि वे आक्रामक रूप से अपवादों को दबा रहे हैं। मूल प्रश्न एक सूची मानता है, इसका उत्तर भी होना चाहिए।
जेसन आर। कोम्ब्स

1
सुपर व्यापक जवाब! महान इसे "स्टाइल" द्वारा विभिन्न वर्गों में विभाजित किया गया है। धन्यवाद!
०१

हालांकि सबसे तेज कौन सा है?
शशांक एस।

12
try:
    s.remove("")
except ValueError:
    print "new_tag_list has no empty string"

ध्यान दें कि यह केवल आपकी सूची से खाली स्ट्रिंग का एक उदाहरण निकाल देगा (जैसा कि आपका कोड भी होगा)। क्या आपकी सूची में एक से अधिक हो सकते हैं?


5

यदि indexखोजा गया स्ट्रिंग नहीं मिलता है, तो ValueErrorआप उसे देख रहे हैं। या तो पकड़ मूल्य:

try:
    i = s.index("")
    del s[i]
except ValueError:
    print "new_tag_list has no empty string"

या उपयोग find, जो उस स्थिति में -1 देता है।

i = s.find("")
if i >= 0:
    del s[i]
else:
    print "new_tag_list has no empty string"

एक सूची विशेषता है? मैं मिल रहा हूँ:>>> s [u'Hello', u'Cool', u'Glam'] >>> i = s.find("") Traceback (most recent call last): File "<pyshell#42>", line 1, in <module> i = s.find("") AttributeError: 'list' object has no attribute 'find'
Zeynel

2
टाइम पीट्सकर का remove()दृष्टिकोण बहुत अधिक प्रत्यक्ष है: यह सीधे दिखाता है कि कोड क्या करना है (वास्तव में इंटरमीडिएट इंडेक्स की कोई आवश्यकता नहीं है i)।
एरिक ओ लेबिगॉट

1
@Zeynel नहीं, यह प्रत्येक पायथन में होना चाहिए, docs.python.org/library/string.html#string.find देखें । लेकिन जैसा कि EOL ने बताया, बस हटाने का उपयोग करना बेहतर है।
फ़िहाग

4

पूर्णता के लिए इस उत्तर को जोड़ना, हालांकि यह केवल कुछ शर्तों के तहत उपयोग करने योग्य है।

यदि आपके पास बहुत बड़ी सूचियाँ हैं, तो सूची के अंत से हटा देने से CPython के आंतरिक होने से बचा जाता है memmove, उन स्थितियों के लिए जहाँ आप सूची को फिर से ऑर्डर कर सकते हैं। यह सूची के अंत से हटाने के लिए एक प्रदर्शन लाभ देता है, क्योंकि इसे हटाने के बाद आपको memmove प्रत्येक आइटम की आवश्यकता नहीं होगी - एक कदम (1) वापस ।
एकबारगी हटाने के लिए प्रदर्शन अंतर स्वीकार्य हो सकता है, लेकिन यदि आपके पास एक बड़ी सूची है और कई मदों को हटाने की आवश्यकता है - तो आप संभवतः एक प्रदर्शन हिट पर ध्यान देंगे।

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

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

def remove_unordered(ls, item):
    i = ls.index(item)
    ls[-1], ls[i] = ls[i], ls[-1]
    ls.pop()

जब itemआप सूची में नहीं होते हैं, तो आप त्रुटि उठाने से बच सकते हैं ।

def remove_unordered_test(ls, item):
    try:
        i = ls.index(item)
    except ValueError:
        return False
    ls[-1], ls[i] = ls[i], ls[-1]
    ls.pop()
    return True

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

इसका परीक्षण करने का एक सरल तरीका, अंतिम तत्व को हटाने के साथ सूची के सामने से हटाने से गति अंतर की तुलना करें:

python -m timeit 'a = [0] * 100000' 'while a: a.remove(0)'

साथ में:

python -m timeit 'a = [0] * 100000' 'while a: a.pop()'

(एक गति का अंतर देता है जहां दूसरा उदाहरण CPython और PyPy के साथ तेज है)।

  1. इस मामले में आप एक का उपयोग करने पर विचार कर सकते हैं set, खासकर अगर सूची डुप्लिकेट को स्टोर करने के लिए नहीं है।
    व्यवहार में हालांकि आपको उत्परिवर्तित डेटा को संग्रहीत करने की आवश्यकता हो सकती है जिसे एक में नहीं जोड़ा जा सकता है set। अगर डेटा आर्डर किया जा सकता है तो btree पर भी जाँच करें।

3

ईक, जटिल कुछ भी मत करो:)

बस filter()अपने टैग। खाली तारों के लिए bool()रिटर्न False, इसलिए के बजाय

new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)

आपको लिखना चाहिए

new_tag_list = filter(bool, f1.striplist(tag_string.split(",") + selected_tags))

या बेहतर अभी तक, इस तर्क को अंदर रखें striplist()ताकि यह पहली बार में खाली तारों को वापस न करे।


धन्यवाद! सभी अच्छे उत्तर लेकिन मुझे लगता है कि मैं इसका उपयोग करूंगा। यह मेरा striplistकार्य है, मैं आपके समाधान को कैसे शामिल करूं: स्ट्रिप्लिस्ट (l) को परिभाषित करें: "" "स्ट्रिप्स व्हाट्सएप से सूची में स्ट्रिंग्स l" "वापसी ([x.strip () के लिए x in l])
Zeynel

1
@Zeynel: निश्चित। आप या तो इस तरह से अपनी सूची समझ के अंदर एक परीक्षण रख सकते हैं: [x.strip() for x in l if x.strip()]या पायथन के अंतर्निहित mapऔर filterइस तरह के कार्यों का उपयोग करें filter(bool, map(str.strip, l)):। यदि आप इसका परीक्षण करना चाहते हैं, तो इंटरएक्टिव इंटरप्रेटर में इसका मूल्यांकन करें filter(bool, map(str.strip, [' a', 'b ', ' c ', '', ' '])):।
dfichter

इस मामले के लिए फ़िल्टर का एक शॉर्टकट है (बूलियन संदर्भ में तत्व का मूल्यांकन करना): पहले तर्क Noneके boolलिए उपयोग करना पर्याप्त है।
19o पर पाउलो स्कर्डी

2

यहाँ से बाहर फेंकने के लिए एक और एक लाइनर दृष्टिकोण है:

next((some_list.pop(i) for i, l in enumerate(some_list) if l == thing), None)

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

सामान्य तौर पर, जब एक-लाइनर समाधान की तलाश होती है जो अपवाद नहीं फेंकती है, तो अगला () जाने का रास्ता है, क्योंकि यह उन कुछ पायथन कार्यों में से एक है जो डिफ़ॉल्ट तर्क का समर्थन करता है।


1

आपको बस इतना करना है

list = ["a", "b", "c"]
    try:
        list.remove("a")
    except:
        print("meow")

लेकिन उस पद्धति का एक मुद्दा है। आपको इसके अलावा कुछ और जगह पर रखना होगा, इसलिए मैंने यह पाया:

list = ["a", "b", "c"]
if "a" in str(list):
    list.remove("a")

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