তালিকার কোনও আইটেম উপস্থিত থাকলে কীভাবে মুছবেন?


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)    
  • যথেষ্ট সহজ, সম্ভবত আমার পছন্দ small ছোট তালিকার জন্য (এক-রেখার প্রতিরোধ করতে পারে না)

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 এর চেয়ে ভাল পারফর্ম করে
  • পিইপি 463 চেষ্টা করার জন্য / এখানে সহজ ব্যবহারযোগ্য যা সাধারণ ব্যবহার ব্যতীত একটি সংক্ষিপ্ত বাক্য গঠন প্রস্তাব করেছিল, কিন্তু এটি অনুমোদিত হয়নি।

তবে কনটেক্সলিবের দমন () প্রসঙ্গের ব্যবস্থাপনার (পাইথন ৩.৪ এ প্রবর্তিত) উপরের কোডটি এটিকে সহজতর করা যেতে পারে:

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)
  • [আপডেট] : পাইথন ২.x এ, (বা যদি প্রথম যুক্তিটি হয় ) এর filter(function, iterable)সমতুল্য ব্যবহৃত হত ; পাইথন ৩.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()
  • * এই লিস্পি স্বাদযুক্ত নির্মাণগুলি পাইথনে কিছুটা এলিয়েন হিসাবে বিবেচনা করা হয়। ২০০৫ সালের দিকে, গাইডো এমনকি filterনামার কথা বলছিলেন - সহচরদের সাথে mapএবং reduce(তারা এখনও যায় নি তবে ফান্টুলস মডিউলে reduceস্থানান্তরিত হয়েছিল, এটি যদি আপনি উচ্চ অর্ডার ফাংশন পছন্দ করেন তবে এক নজরে মূল্যবান )।

4) গাণিতিক শৈলী:

পিইপি 202 দ্বারা 2.0 সংস্করণে প্রবর্তিত হওয়ার পরে পাইথনে লিস্ট ম্যানিপুলেশনের জন্য তালিকা বোধগম্য পছন্দসই স্টাইল হয়ে ওঠে । এটি পিছনে পিছনে যুক্তি হল এই তালিকা comprehensions পরিস্থিতিতে তালিকা তৈরি করতে যেখানে আরও সংক্ষিপ্ত পন্থা প্রদান হয় map()এবং filter()এবং / অথবা নেস্টেড loops বর্তমানে ব্যবহার করা হবে।

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'
জিনেল

2
টাইম পিটসেকারের remove()দৃষ্টিভঙ্গি অনেক বেশি সরাসরি: এটি কোডটি কী বোঝাতে চাইছে তা সরাসরি দেখায় (আসলে কোনও মধ্যবর্তী সূচকের প্রয়োজন নেই i)।
এরিক হে লেবিগোট

1
@ জেইনেল না, এটি প্রতিটি পাইথনে থাকা উচিত, ডকস.পাইথন.আর . / লাইবারি / স্ট্রিংHtml#string.find দেখুন । তবে ইওএল হিসাবে উল্লেখ করা হয়েছে, কেবল অপসারণটি ব্যবহার করা ভাল a
ফিহাগ

4

সম্পূর্ণরূপে এই উত্তর যুক্ত করা, যদিও এটি নির্দিষ্ট কিছু শর্তে কেবল ব্যবহারযোগ্য।

আপনার যদি খুব বড় তালিকা থাকে তবে তালিকার শেষে থেকে অপসারণ সিপিথন অভ্যন্তরীন হওয়াগুলি এড়িয়ে চলে memmove, আপনি সেই পরিস্থিতিতে যেখানে তালিকাটি পুনরায় অর্ডার করতে পারবেন। এটি তালিকার শেষে থেকে অপসারণের জন্য একটি পারফরম্যান্স লাভ দেয়, যেহেতু এটি অপসারণের পরে memmove প্রতিটি আইটেমের প্রয়োজন হবে না - এক ধাপ পিছনে (1)
এক-অফ অপসারণের জন্য পারফরম্যান্সের পার্থক্যটি গ্রহণযোগ্য হতে পারে তবে আপনার যদি একটি বড় তালিকা থাকে এবং অনেকগুলি আইটেম সরিয়ে ফেলতে হয় - আপনি সম্ভবত একটি পারফরম্যান্স হিট লক্ষ্য করবেন।

যদিও স্বীকার করা যায় যে, এই ক্ষেত্রেগুলিতে পুরো তালিকা অনুসন্ধান করা একটি পারফরম্যান্স বাধাও হতে পারে, যদি না তালিকাগুলি তালিকার বেশিরভাগ অংশে থাকে unless

এই পদ্ধতিটি আরও দক্ষ অপসারণের জন্য ব্যবহার করা যেতে পারে,
যতক্ষণ না তালিকাকে পুনরায় অর্ডার করা গ্রহণযোগ্য। (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. আমি সিপিথন দিয়ে এটি পরীক্ষা করার সময়, সম্ভবত এটির / সম্ভবত অন্যান্য সমস্ত পাইথন বাস্তবায়ন তালিকা অভ্যন্তরীণভাবে সংরক্ষণ করার জন্য একটি অ্যারে ব্যবহার করে। সুতরাং যদি না তারা দক্ষ তালিকার পুনরায় আকার নির্ধারণের জন্য নকশাকৃত একটি পরিশীলিত ডেটা স্ট্রাকচার ব্যবহার না করেন তবে তাদের কার্য সম্পাদনের বৈশিষ্ট্যগুলি একই রকম হয়।

এটি পরীক্ষা করার একটি সহজ উপায়, তালিকার সামনের অংশ থেকে অপসারণের সাথে গতির পার্থক্যটি শেষ উপাদানটি সরিয়ে দিয়ে তুলনা করুন:

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

সঙ্গে:

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

(দ্বিতীয়টি সিপিথন এবং পাইপাই সহ দ্রুততর যেখানে গতিবেগের গতির পার্থক্যের একটি অর্ডার দেয়)।

  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 এর জন্য x])
জ্যানেল

1
@ জেইনেল: অবশ্যই হয় আপনি এই মত আপনার তালিকার ধী ভিতরে একটি পরীক্ষা করা যেতে পারে: [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 ', '', ' ']))
ডিফিটার

ফিল্টারটির এই ক্ষেত্রে শর্টকাট রয়েছে (বুলিয়ান প্রসঙ্গে উপাদানটির মূল্যায়ন করা): ব্যবহার Nonebool প্রথম যুক্তির পরিবর্তে করা যথেষ্ট।
পাওলো স্কার্ডাইন

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
আপনার অন্তর্নির্মিত তালিকাটি ওভাররাইট করা উচিত নয় । এবং ২ য় স্নিপেটে স্ট্রিতে রূপান্তরকরণের প্রয়োজন নেই।
রবার্ট ক্যাস্পারি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.