স্ট্রিংয়ের তালিকা থেকে খালি স্ট্রিংগুলি সরান


683

আমি পাইথনের স্ট্রিংগুলির তালিকা থেকে সমস্ত খালি স্ট্রিংগুলি সরাতে চাই।

আমার ধারণাটি এমন দেখাচ্ছে:

while '' in str_list:
    str_list.remove('')

এটি করার জন্য আর কোনও অজগর উপায় আছে কি?


45
@ আইভো, এই বিবৃতিগুলির কোনওটিই সত্য নয়। আপনার পুনরাবৃত্তি করে এমন কোনও তালিকা আপনাকে কখনও সংশোধন করা উচিত নয় for x in listআপনি যদি ব্যবহার করেন while loopতবে তা ঠিক আছে। প্রদর্শিত লুপটি খালি স্ট্রিংগুলি সরিয়ে ফেলবে যতক্ষণ না খালি আরও বেশি স্ট্রিং থাকে এবং তারপরে বন্ধ না হয়। আমি আসলে প্রশ্নটির দিকেও নজর রাখিনি (কেবল শিরোনাম) তবে আমি ঠিক একই লুপটি দিয়ে একটি সম্ভাবনা হিসাবে উত্তর দিয়েছি! আপনি যদি মেমরির স্বার্থে বোধগম্য বা ফিল্টার ব্যবহার করতে না চান তবে এটি একটি অত্যন্ত অজগর সমাধান।
অ্যারোনস্টার্লিং

4
আপনি যে তালিকাটি পুনরাবৃত্তি করছেন তা কখনও পরিবর্তন না করার জন্য একটি খুব কার্যকর পয়েন্ট :)
এডওয়ার্ড লুকা

1
@ এডুয়ার্ড লুকা যদি কোনও তালিকার পুনরাবৃত্তির বিন্দুটি পরিবর্তন করা হয়, তবে এটি আপনার করা উচিত তার বিপরীত। আপনাকে কেবল সতর্কতা অবলম্বন করতে হবে যে আপনি জানেন যে এটি করে আপনি কোনও অপ্রত্যাশিত আচরণের কারণ হয়ে উঠছেন না।
জেএফএ

1
@ এডুয়ার্ডলুকা, @ জেএফএ: মুল বক্তব্যটি হ'ল তিনি কোনও তালিকাতে পুনরাবৃত্তি করছেন না। তিনি যদি ফর্মটিতে কিছু লিখতেন for var in list:তবে এখানে তিনি লিখেছেন while const in list:। যা কোনও কিছুর উপরে পুনরাবৃত্তি করছে না। শর্তটি মিথ্যা না হওয়া পর্যন্ত এটি কেবল একই কোডটি পুনরাবৃত্তি করে।
ক্যামিয়ন

উত্তর:


1151

আমি ব্যবহার করব filter:

str_list = filter(None, str_list)
str_list = filter(bool, str_list)
str_list = filter(len, str_list)
str_list = filter(lambda item: item, str_list)

পাইথন 3 একটি পুনরুক্তি ফিরিয়ে দেয় filter, তাই কোনও কলটিতে মোড়ানো উচিতlist()

str_list = list(filter(None, str_list))

11
আপনি হন, তাহলে যে পারফরম্যান্সের জন্য চাপা, itertoolএরifilter এমনকি faster- হয় >>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000) 2.3468542098999023; >>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000) 0.04442191123962402
হামফ্রে বোগার্ট

4
@ cpburnz খুব সত্য। যাইহোক, ifilterফলাফলগুলি অলসভাবে মূল্যায়ন করা হয় , একসাথে নয় — আমি যুক্তি দিয়ে বলছি যে বেশিরভাগ ক্ষেত্রেই ifilterভাল। আকর্ষণীয় যে filterব্যবহারটি কিছুক্ষণের ifilterমধ্যে মোড়কের চেয়ে আরও দ্রুত list
হামফ্রে বোগার্ট

3
যদি আপনি সংখ্যার তালিকায় এটি করেন তবে নোট করুন যে শূন্যগুলিও সরানো হবে (দ্রষ্টব্য: আমি কেবল প্রথম 3 টি পদ্ধতি ব্যবহার করেছি), সুতরাং আপনার একটি বিকল্প পদ্ধতি প্রয়োজন।
স্নোরিংফ্রোগ

2
এটি কেবল গতিতে মনোনিবেশ করে, সমাধানটি কীভাবে পাই তা পাই নয় (কী প্রশ্নটি জিজ্ঞাসা করা হয়েছিল)। তালিকাগুলি হ'ল পাইথোনিক সমাধান এবং ফিল্টারটি কেবল তখনই ব্যবহার করা উচিত যদি লিখনকম্পটি বাধা হয়ে থাকে তা যদি প্রোফাইলিং প্রমাণ করে।
ট্রিটিয়াম

3
@ যিনি-সম্পর্কে-বা-স্পষ্ট-পাইথন -3-এর উল্লেখ করেছেন, দয়া করে কেবল উত্তরটি সম্পাদনা করুন এবং আপডেট করুন। আমরা কেবল পাইথন 2 এর জন্য আলোচনা করছিলাম যখন এই প্রশ্ন জিজ্ঞাসা করা হয়েছিল, এমনকি পাইথন 3 প্রায় 2 বছর প্রকাশিত হয়েছিল। তবে পাইথন 2 এবং 3 ফলাফল উভয়ই আপডেট করুন।
livibetter

236

একটি তালিকা বোধগম্যতা সর্বাধিক পাইথোনিক উপায়:

>>> strings = ["first", "", "second"]
>>> [x for x in strings if x]
['first', 'second']

যদি তালিকাটি অবশ্যই স্থানে পরিবর্তন করতে হবে, কারণ অন্যান্য উল্লেখ রয়েছে যা অবশ্যই আপডেট হওয়া ডেটা দেখতে হবে, তারপরে একটি স্লাইস অ্যাসাইনমেন্ট ব্যবহার করুন:

strings[:] = [x for x in strings if x]

16
আমি এই সমাধানটি পছন্দ করি কারণ এটি সহজেই গ্রহণযোগ্য। যদি আমি না শুধুমাত্র ফাঁকা স্ট্রিং কিন্তু স্ট্রিং যে শুধু হোয়াইটস্পেস হয় মুছে ফেলার জন্য উদাহরণস্বরূপ প্রয়োজন: [x for x in strings if x.strip()]
বন্ড

67

ফিল্টার আসলে এর জন্য একটি বিশেষ বিকল্প রয়েছে:

filter(None, sequence)

এটি মিথ্যাতে মূল্যায়নকারী সমস্ত উপাদানগুলি ফিল্টার করে দেবে। এখানে প্রকৃত কলযোগ্য যেমন বুল, লেন ইত্যাদি ব্যবহার করার দরকার নেই।

এটি মানচিত্রের মতো সমান দ্রুত (বুল, ...)


5
আসলে এটি একটি অজগর প্রতিমা। আমি কেবল এখনও ফিল্টার () ব্যবহার করি, অন্যদিকে অন্যত্র তালিকার বোধগম্যতা গ্রহণ করে।
ক্যালিসিন

24
>>> lstr = ['hello', '', ' ', 'world', ' ']
>>> lstr
['hello', '', ' ', 'world', ' ']

>>> ' '.join(lstr).split()
['hello', 'world']

>>> filter(None, lstr)
['hello', ' ', 'world', ' ']

সময় তুলনা

>>> from timeit import timeit
>>> timeit('" ".join(lstr).split()', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
4.226747989654541
>>> timeit('filter(None, lstr)', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
3.0278358459472656

লক্ষ করুন যে, filter(None, lstr)একটি স্পেস দিয়ে খালি স্ট্রিং মুছে যায় না ' ', এটি শুধুমাত্র দূরে আলুবোখারা ''যখন ' '.join(lstr).split()অপসারণ উভয়।

filter()সাদা স্থানের স্ট্রিংগুলি মুছে ফেলাতে ব্যবহার করতে , এটি আরও অনেক বেশি সময় নেয়:

>>> timeit('filter(None, [l.replace(" ", "") for l in lstr])', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
18.101892948150635

শব্দের স্ট্রিংয়ের মধ্যে আপনার স্থান থাকলে এটি কাজ করবে না। উদাহরণস্বরূপ: ['হ্যালো ওয়ার্ল্ড', '', 'হ্যালো', '']। >> ['হেলিওর্ল্ড', '', 'হ্যালো', ''] তালিকার কোনও আইটেমের মধ্যে ফাঁক রাখা ছাড়া অন্যদের অপসারণ করার কোনও বিকল্প আছে কি?
রেহান_ম্ন

লক্ষ্য করুন যে filter(None, lstr)একটি ফাঁকা স্ট্রিং কোনও স্থানের সাথে সরিয়ে দেয় না' ' হ্যাঁ, কারণ এটি একটি খালি স্ট্রিং নয়।
এএমসি

15

@ Ib33X এর থেকে উত্তর দারুণ। আপনি যদি প্রতিটি খালি স্ট্রিংটি সরিয়ে ফেলতে চান তবে pped আপনারও স্ট্রিপ পদ্ধতিটি ব্যবহার করতে হবে। অন্যথায়, যদি এটি সাদা জায়গা করে থাকে তবে এটি খালি স্ট্রিংটিও ফিরিয়ে দেবে। পছন্দ করুন, "" এই উত্তরের জন্যও বৈধ হবে। সুতরাং, দ্বারা অর্জন করা যেতে পারে।

strings = ["first", "", "second ", " "]
[x.strip() for x in strings if x.strip()]

এর উত্তর হবে ["first", "second"]। পরিবর্তে
আপনি যদি filterপদ্ধতিটি ব্যবহার করতে চান তবে আপনি পছন্দ করতে পারেন
list(filter(lambda item: item.strip(), strings))। এটি একই ফলাফল দেয়।


12

যদি x এর পরিবর্তে আমি খালি স্ট্রিংগুলি মুছে ফেলার জন্য X! = '' ব্যবহার করি। এটার মত:

str_list = [x for x in str_list if x != '']

এটি আপনার তালিকার মধ্যে কোনও ডেটা টাইপ সংরক্ষণ করবে will এছাড়াও, যদি আপনার তালিকার পূর্ণসংখ্যা থাকে এবং 0 এর মধ্যে একটি হয় তবে এটিও সংরক্ষণ করা হবে।

উদাহরণ স্বরূপ,

str_list = [None, '', 0, "Hi", '', "Hello"]
[x for x in str_list if x != '']
[None, 0, "Hi", "Hello"]

2
যদি আপনার তালিকাগুলিতে পৃথক প্রকারের (তবে কিছুই না) থাকে তবে আপনার আরও বড় সমস্যা হতে পারে।
ট্রিটিয়াম

কি ধরণের? আমি ইন্টি এবং অন্যান্য সংখ্যাসূচক প্রকার, স্ট্রিং, তালিকাগুলি, টিউপস, সেট এবং কোনওটিই নেই এবং সেখানে কোনও সমস্যা নেই tried আমি দেখতে পাচ্ছিলাম যে যদি কোনও ব্যবহারকারীর সংজ্ঞায়িত প্রকারগুলি থাকে যা str পদ্ধতি সমর্থন করে না তবে সমস্যা হতে পারে। আমার কি অন্য কোনও বিষয়ে উদ্বিগ্ন হওয়া উচিত?
থিরুভেনকদম

1
আপনার যদি str_list = [None, '', 0, "Hi", '', "Hello"]এটি থাকে তবে এটি একটি খারাপ নকশাকৃত অ্যাপ্লিকেশনটির একটি চিহ্ন। আপনার একাধিক ইন্টারফেস (টাইপ) এবং একই তালিকায় থাকা উচিত নয়
ট্রিটিয়াম

3
ডিবি থেকে ডেটা পুনরুদ্ধার করা হচ্ছে? অটোমেটেড টেস্টিং করার সময় কোনও ফাংশনের পক্ষে যুক্তিগুলির তালিকা?
thiruvenkadam

3
এগুলি সাধারণত টিপলস হয়।
ট্রিটিয়াম 21

7

আপনার তালিকার আকারের উপর নির্ভর করে আপনি যদি নতুন তালিকা তৈরি না করে list.rem () ব্যবহার করেন তবে এটি সবচেয়ে কার্যকর হতে পারে:

l = ["1", "", "3", ""]

while True:
  try:
    l.remove("")
  except ValueError:
    break

এটি একটি নতুন তালিকা তৈরি না করার সুবিধা রয়েছে, তবে প্রতিবার শুরু থেকে অনুসন্ধান করার অসুবিধা, যদিও while '' in lউপরে প্রস্তাবিত হিসাবে ভিন্ন হিসাবে এটি কেবল একবার প্রতি একবার অনুসন্ধান করা প্রয়োজন ''(অবশ্যই সেরাটি রাখার উপায় আছে) উভয় পদ্ধতি, তবে এটি আরও জটিল)।


1
আপনি কাজ করে তালিকাটি সম্পাদনা করতে পারেন ary[:] = [e for e in ary if e]। নিয়ন্ত্রণ প্রবাহের জন্য অনেক ক্লিনার এবং ব্যতিক্রম ব্যবহার করে না।
Krzysztof Karski

2
ঠিক আছে, এটি আসলে "স্থানে" নয় - আমি খুব নিশ্চিত যে এটি একটি নতুন তালিকা তৈরি করে এবং এটি কেবল পুরানো ব্যক্তির নামে বরাদ্দ করেছে।
অ্যান্ড্রু জাফ

এটি খুব খারাপভাবে সম্পাদন করে কারণ প্রতিটি অপসারণের মেমরিতে ডেটার লেজটি প্রায় বদলে যায়। এক হিট থেকে সমস্ত অপসারণ করা ভাল।
উইম

7

মনে রাখবেন যে যদি আপনি সাদা জায়গাগুলিকে স্ট্রিংয়ের মধ্যে রাখতে চান তবে আপনি কিছু উপায় ব্যবহার করে অনিচ্ছাকৃতভাবে সেগুলি সরাতে পারেন। আপনার যদি এই তালিকা থাকে

['হ্যালো ওয়ার্ল্ড', '', '', 'হ্যালো'] আপনি কী চাইবেন ['হ্যালো ওয়ার্ল্ড', 'হ্যালো']

যে কোনও ধরণের সাদা স্থানকে খালি স্ট্রিংয়ে রূপান্তর করতে প্রথমে তালিকাটি ট্রিম করুন:

space_to_empty = [x.strip() for x in _text_list]

তারপরে তাদের তালিকা থেকে খালি স্ট্রিংটি সরান

space_clean_list = [x for x in space_to_empty if x]

যদি আপনি সাদা জায়গাগুলিকে কোনও স্ট্রিংয়ের মধ্যে রাখতে চান তবে আপনি কিছু উপায় ব্যবহার করে অনিচ্ছাকৃতভাবে সেগুলি সরাতে পারেন। এই পদ্ধতির মত, তারপর?
এএমসি

ধন্যবাদ বন্ধু, এটি আমার জন্য সামান্য পরিবর্তন নিয়ে কাজ করেছে। অর্থাতspace_clean_list = [x.strip() for x in y if x.strip()]
মুহাম্মদ মেহরান খান আত্তারী

6

ব্যবহার filter:

newlist=filter(lambda x: len(x)>0, oldlist) 

নির্দেশিত হিসাবে ফিল্টার ব্যবহারের ত্রুটিগুলি হ'ল এটি বিকল্পগুলির চেয়ে ধীর; এছাড়াও, lambdaসাধারণত ব্যয়বহুল।

বা আপনি সবচেয়ে সহজ এবং সবচেয়ে পুনরাবৃত্তি জন্য যেতে পারেন:

# I am assuming listtext is the original list containing (possibly) empty items
for item in listtext:
    if item:
        newlist.append(str(item))
# You can remove str() based on the content of your original list

এটি পদ্ধতিগুলির মধ্যে সবচেয়ে স্বজ্ঞাত এবং এটি শালীন সময়ে এটি করে।


9
তাই আপনাকে স্বাগতম। আপনি অবহেলা করা হয়নি। আপনার উপর কোনও আপত্তিজনক আক্রমণকারীর দ্বারা আক্রমণ করা হয়নি। আপনাকে প্রতিক্রিয়া জানানো হয়েছে। পরিবর্ধক: ফিল্টারটির জন্য আপনার প্রস্তাবিত প্রথম আরগটি তার চেয়েও lambda x: len(x)খারাপ lambda x : xযা বাছাই করা উত্তরের 4 টি সমাধানের মধ্যে সবচেয়ে খারাপ। সঠিক কার্যকারিতা পছন্দ করা হয়, তবে পর্যাপ্ত নয়। ডাউন কার্ট বোতামের উপরে আপনার কার্সারটিকে ঘোরাও: এটি বলছে "এই উত্তরটি কার্যকর নয়"।
জন মাচিন

5

আজিজ আল্টোর রিপোর্ট অনুসারে filter(None, lstr)কোনও স্থানের সাথে খালি স্ট্রিংগুলি মুছে ফেলা হয় না ' 'তবে আপনি যদি নিশ্চিত হন যে lrc কেবলমাত্র স্ট্রিং ব্যবহার করতে পারেন তবে আপনি ব্যবহার করতে পারেনfilter(str.strip, lstr)

>>> lstr = ['hello', '', ' ', 'world', ' ']
>>> lstr
['hello', '', ' ', 'world', ' ']
>>> ' '.join(lstr).split()
['hello', 'world']
>>> filter(str.strip, lstr)
['hello', 'world']

আমার পিসির সাথে সময়ের তুলনা করুন

>>> from timeit import timeit
>>> timeit('" ".join(lstr).split()', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
3.356455087661743
>>> timeit('filter(str.strip, lstr)', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
5.276503801345825

মুছে ফেলার জন্য দ্রুততম সমাধান ''এবং একটি স্পেস দিয়ে খালি স্ট্রিং ' 'দেহাবশেষ ' '.join(lstr).split()

একটি মন্তব্যে হিসাবে রিপোর্ট করা হয়েছে যদি আপনার স্ট্রিংয়ের মধ্যে ফাঁকা স্থান থাকে তবে পরিস্থিতি আলাদা।

>>> lstr = ['hello', '', ' ', 'world', '    ', 'see you']
>>> lstr
['hello', '', ' ', 'world', '    ', 'see you']
>>> ' '.join(lstr).split()
['hello', 'world', 'see', 'you']
>>> filter(str.strip, lstr)
['hello', 'world', 'see you']

আপনি দেখতে পাচ্ছেন যে filter(str.strip, lstr)এটির ফাঁকা স্থান দিয়ে স্ট্রিংগুলি সংরক্ষণ করুন তবে ' '.join(lstr).split()এই স্ট্রিংগুলিকে বিভক্ত করবেন।


1
এটি কেবল তখনই কাজ করে যদি আপনার স্ট্রিংগুলিতে স্পেস না থাকে। অন্যথায়, আপনি সেই স্ট্রিংগুলিও বিভক্ত করছেন।
ফিলিস্ক্লিক

1
@ বেনপলিনস্কি যেমন আপনি প্রতিবেদন করেছেন joinসমাধানটি স্থানের সাথে স্ট্রিংগুলিকে বিভক্ত করবে তবে ফিল্টারটি তা করবে না। আপনি মন্তব্য করার জন্য আপনাকে ধন্যবাদ আমি আমার উত্তর উন্নত।
পাওলো মেলচিয়েরে

-1

সেরা উত্তরগুলি যোগ করুন:

1. স্ট্রিপিং ছাড়াই এমটিপিটিস দূর করুন:

এটি হ'ল, সমস্ত স্থানের স্ট্রিংগুলি বজায় রাখা আছে:

slist = list(filter(None, slist))

পেশাদাররা:

  • সবচেয়ে সহজ;
  • দ্রুততম (নীচে মানদণ্ড দেখুন)।

২. স্ট্রিপিংয়ের পরে শূন্যস্থান দূর করতে ...

২ ক ... যখন স্ট্রিংগুলিতে শব্দের মধ্যে ফাঁকা স্থান থাকে না:

slist = ' '.join(slist).split()

পেশাদাররা:

  • ছোট কোড
  • দ্রুত (তবে মেমোরির কারণে বড় ডেটাসেটগুলির সাথে দ্রুত নয় তবে @ পাওলো-মেলচিয়েরের ফলাফলগুলির বিপরীতে)

2. বি ... স্ট্রিংগুলিতে শব্দের মধ্যে ফাঁকা স্থান থাকে?

slist = list(filter(str.strip, slist))

পেশাদাররা:

  • দ্রুততম;
  • কোড বোধগম্যতা।

একটি 2018 মেশিনে মানদণ্ড:

## Build test-data
#
import random, string
nwords = 10000
maxlen = 30
null_ratio = 0.1
rnd = random.Random(0)                  # deterministic results
words = [' ' * rnd.randint(0, maxlen)
         if rnd.random() > (1 - null_ratio)
         else
         ''.join(random.choices(string.ascii_letters, k=rnd.randint(0, maxlen)))
         for _i in range(nwords)
        ]

## Test functions
#
def nostrip_filter(slist):
    return list(filter(None, slist))

def nostrip_comprehension(slist):
    return [s for s in slist if s]

def strip_filter(slist):
    return list(filter(str.strip, slist))

def strip_filter_map(slist): 
    return list(filter(None, map(str.strip, slist))) 

def strip_filter_comprehension(slist):  # waste memory
    return list(filter(None, [s.strip() for s in slist]))

def strip_filter_generator(slist):
    return list(filter(None, (s.strip() for s in slist)))

def strip_join_split(slist):  # words without(!) spaces
    return ' '.join(slist).split()

## Benchmarks
#
%timeit nostrip_filter(words)
142 µs ± 16.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit nostrip_comprehension(words)
263 µs ± 19.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit strip_filter(words)
653 µs ± 37.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit strip_filter_map(words)
642 µs ± 36 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit strip_filter_comprehension(words)
693 µs ± 42.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit strip_filter_generator(words)
750 µs ± 28.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit strip_join_split(words)
796 µs ± 103 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

s and s.strip()সহজ সরল করা যেতে পারে s.strip()
এএমসি

s and s.strip()প্রয়োজন যদি আমরা সম্পূর্ণরূপে প্রতিলিপি করতে চাই filter(None, words), গৃহীত উত্তর। আমি উপরে এক্স 2 নমুনা ফাংশনগুলি সংশোধন করেছি এবং এক্স 2 খারাপগুলি বাদ দিয়েছি।
ankostis

-2

শূন্যস্থান এবং খালি মানগুলির সংমিশ্রণ সহ একটি তালিকার জন্য, সাধারণ তালিকা অনুধাবন ব্যবহার করুন -

>>> s = ['I', 'am', 'a', '', 'great', ' ', '', '  ', 'person', '!!', 'Do', 'you', 'think', 'its', 'a', '', 'a', '', 'joke', '', ' ', '', '?', '', '', '', '?']

সুতরাং, আপনি দেখতে পারেন, এই তালিকার মধ্যে ফাঁকা স্থান এবং নাল উপাদানগুলির সংমিশ্রণ রয়েছে। স্নিপেট ব্যবহার করে -

>>> d = [x for x in s if x.strip()]
>>> d
>>> d = ['I', 'am', 'a', 'great', 'person', '!!', 'Do', 'you', 'think', 'its', 'a', 'a', 'joke', '?', '?']
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.