web-dev-qa-db-ja.com

文字列のリストから空の文字列を削除する

私はpythonの文字列のリストからすべての空の文字列を削除したいです。

私の考えはこのようになります:

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

これを行うための他のPythonic方法はありますか?

560
zerodx

filter :を使います。

str_list = filter(None, str_list) # fastest
str_list = filter(bool, str_list) # fastest
str_list = filter(len, str_list)  # a bit slower
str_list = filter(lambda item: item, str_list) # slower than list comprehension

Python 3はfilterからイテレータを返すので、list()への呼び出しでラップする必要があります

str_list = list(filter(None, str_list)) # fastest

など

テスト:

>>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)
2.4797441959381104
>>> timeit('filter(bool, str_list)', 'str_list=["a"]*1000', number=100000)
2.4788150787353516
>>> timeit('filter(len, str_list)', 'str_list=["a"]*1000', number=100000)
5.2126238346099854
>>> timeit('[x for x in str_list if x]', 'str_list=["a"]*1000', number=100000)
13.354584932327271
>>> timeit('filter(lambda item: item, str_list)', 'str_list=["a"]*1000', number=100000)
17.427681922912598
956
livibetter

リスト内包表記

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

出力:['first', 'second']

編集:提案どおりに短縮

193
Ib33X

filterは実際にこれのための特別なオプションを持っています:

filter(None, sequence)

Falseと評価されたすべての要素を除外します。ここではbool、lenなどの実際の呼び出し可能オブジェクトを使用する必要はありません。

地図と同じくらい速い(bool、...)

60
>>> 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
20
Aziz Alto

If xの代わりに、空の文字列を削除するためだけにif X!= ''を使用します。このような:

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

これはあなたのリストの中にNoneデータ型を保存します。また、あなたのリストが整数を持っていて、0がそれらのうちの1つであるならば、それはまた保存されます。

例えば、

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

@ Ib33Xからの返信は素晴らしいです。取り除いた後、空の文字列をすべて削除したい場合。あなたもストリップ法を使用する必要があります。それ以外の場合は、空白がある場合も空の文字列を返します。のように、 ""もその答えに有効です。だから、によって達成することができます。

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

これに対する答えは["first", "second"]です。
代わりにfilterメソッドを使いたい場合は、次のようにします。
list(filter(lambda item: item.strip(), strings))。これは同じ結果になります。

10
ssi-anik

リストのサイズによっては、新しいリストを作成するのではなくlist.remove()を使用する方が最も効率的です。

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

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

これには、新しいリストを作成しないという利点がありますが、毎回最初から検索する必要があるという欠点があります。ただし、上記で提案したwhile '' in lを使用するのとは異なり、''(両方の方法の長所を維持する方法は確かにありますが、より複雑です)。

8
Andrew Jaffe

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

これは最も直感的な方法であり、まともな時間で行われます。

7
Aamir Mushtaq

の空白を文字列 の中に入れたい場合は、いくつかの方法を使用して意図せずに空白を削除する可能性があります。このリストがあれば

['hello world'、 ''、 ''、 'hello']あなたが望むかもしれないもの['hello world'、 'hello']

最初にリストをトリムして、任意のタイプの空白を空の文字列に変換します。

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

それからそれらのリストから空の文字列を削除します

space_clean_list = [x for x in space_to_empty if x]
5
Reihan_amn

Aziz Altoによって報告されているようにfilter(None, lstr)はスペース' 'を持つ空の文字列を削除しませんが、lstrが文字列のみを含むことが確実ならばfilter(str.strip, lstr)を使用できます。

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

私のPCの時間を比較する

>>> 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()はこの文字列を分割します。

5

ストリッピング後に空の部分をなくすには:

slist = map(lambda s: s and s.strip(), slist)
slist = filter(None, slist)

いくつかのPRO:

  • メモリを節約するために、ジェネレータに基づいて遅延する。
  • コードの適切な理解可能性
  • 速く、選択的に組み込み関数と内包表記を使います。

    def f1(slist):
        slist = [s and s.strip() for s in slist]
        return list(filter(None, slist))
    
    def f2(slist):
        slist = [s and s.strip() for s in slist]
        return [s for s in slist if s]
    
    
    def f3(slist):
        slist = map(lambda s: s and s.strip(), slist)
        return list(filter(None, slist))
    
    def f4(slist):
        slist = map(lambda s: s and s.strip(), slist)
        return [s for s in slist if s]
    
    %timeit f1(words)
    10000 loops, best of 3: 106 µs per loop
    
    %timeit f2(words)
    10000 loops, best of 3: 126 µs per loop
    
    %timeit f3(words)
    10000 loops, best of 3: 165 µs per loop
    
    %timeit f4(words)
    10000 loops, best of 3: 169 µs per loop
    
0
ankostis