Pythonの文字列リストからすべての空の文字列を削除したいのですが。
私の考えは次のようになります:
while '' in str_list:
str_list.remove('')
これを行うためのもっとpythonicな方法はありますか?
for var in list:
で書いていたとしたら彼はそうするだろうが、ここでは彼が書いたwhile const in list:
。何も繰り返されません。条件が偽になるまで同じコードを繰り返すだけです。
Pythonの文字列リストからすべての空の文字列を削除したいのですが。
私の考えは次のようになります:
while '' in str_list:
str_list.remove('')
これを行うためのもっとpythonicな方法はありますか?
for var in list:
で書いていたとしたら彼はそうするだろうが、ここでは彼が書いたwhile const in list:
。何も繰り返されません。条件が偽になるまで同じコードを繰り返すだけです。
回答:
私は使用します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)
Python 3はからイテレータを返すfilter
ため、への呼び出しでラップする必要がありますlist()
str_list = list(filter(None, str_list))
itertool
「sが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
。
ifilter
結果は一気に評価されるのではなく、遅延評価されifilter
ます。ほとんどの場合、結果が優れていると私は主張します。使用したことは興味深いがfilter
、まだ速いラップよりもあるifilter
にlist
かかわらず。
リスト内包表記の使用は、最もPython的な方法です。
>>> strings = ["first", "", "second"]
>>> [x for x in strings if x]
['first', 'second']
リストをインプレースで変更する必要がある場合、更新されたデータを参照する必要がある他の参照があるため、スライス割り当てを使用します。
strings[:] = [x for x in strings if x]
[x for x in strings if x.strip()]
。
filterは実際にはこれのための特別なオプションを持っています:
filter(None, sequence)
Falseと評価されるすべての要素をフィルターで除外します。ここでは、bool、lenなどの実際の呼び出し可能オブジェクトを使用する必要はありません。
map(bool、...)と同じくらい高速です
>>> 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)
は空白の空の文字列を削除しないことに注意してください' '
。これは空の文字列ではないためです。
@ Ib33Xからの返信は素晴らしいです。空の文字列をすべて削除したい場合は、削除してください。stripメソッドも使用する必要があります。それ以外の場合、空白がある場合は空の文字列も返します。たとえば、「」もその回答に有効です。だから、によって達成することができます。
strings = ["first", "", "second ", " "]
[x.strip() for x in strings if x.strip()]
これに対する答えはになります["first", "second"]
。
代わりにメソッド
を使用したい場合filter
は、のようにすることができます
list(filter(lambda item: item.strip(), strings))
。これは同じ結果を与えます。
if xの代わりに、空の文字列を削除するためにif X!= ''を使用します。このような:
str_list = [x for x in str_list if x != '']
これにより、リスト内のNoneデータ型が保持されます。また、リストに整数があり、そのうちの1つが0の場合、リストも保持されます。
例えば、
str_list = [None, '', 0, "Hi", '', "Hello"]
[x for x in str_list if x != '']
[None, 0, "Hi", "Hello"]
str_list = [None, '', 0, "Hi", '', "Hello"]
は、アプリケーションの設計が不十分であることを示しています。同じリストに複数のインターフェース(タイプ)とNoneを含めることはできません。
リストのサイズによっては、新しいリストを作成するのではなく、list.remove()を使用するのが最も効率的です。
l = ["1", "", "3", ""]
while True:
try:
l.remove("")
except ValueError:
break
これには、新しいリストを作成しないという利点がありますが、毎回最初から検索する必要があるという欠点があります。 while '' in l
上記の提案、発生ごとに1回だけ検索する必要''
があります(確かに最善の方法を維持する方法があります。両方の方法ですが、より複雑です)。
ary[:] = [e for e in ary if e]
ます。はるかにクリーンで、制御フローの例外を使用しません。
文字列内の空白を保持したい場合は、、いくつかの方法を使用して意図せずに削除する可能性があることください。このリストがあれば
['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]
space_clean_list = [x.strip() for x in y if x.strip()]
使用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
これは最も直感的な方法であり、適切な時間で実行できます。
lambda x: len(x)
場合よりも悪いですlambda x : x
。正しく機能することが望ましいが、十分ではない。カーソルを下向き投票ボタンの上に置くと、「この回答は役に立ちません」と表示されます。
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()
この文字列は分割されます。
join
ソリューションを報告した@BenPolinsky はスペースで文字列を分割しますが、フィルターは分割しません。コメントありがとうございます私は私の答えを改善しました。
つまり、すべてのスペース文字列が保持されます。
slist = list(filter(None, slist))
PRO:
slist = ' '.join(slist).split()
PRO:
slist = list(filter(str.strip, slist))
PRO:
## 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)
、受け入れられた答え。上記のx2のサンプル関数を修正し、x2の悪い関数を削除しました。
スペースと空の値を組み合わせたリストの場合は、単純なリスト内包表記を使用します-
>>> s = ['I', 'am', 'a', '', 'great', ' ', '', ' ', 'person', '!!', 'Do', 'you', 'think', 'its', 'a', '', 'a', '', 'joke', '', ' ', '', '?', '', '', '', '?']
ご覧のとおり、このリストにはスペースとnull要素の組み合わせが含まれています。スニペットの使用-
>>> d = [x for x in s if x.strip()]
>>> d
>>> d = ['I', 'am', 'a', 'great', 'person', '!!', 'Do', 'you', 'think', 'its', 'a', 'a', 'joke', '?', '?']
for x in list
場合は問題ありませんwhile loop
。示されているループは、空の文字列がなくなるまで空の文字列を削除し、停止します。私は実際には質問(タイトルだけ)も見ていませんでしたが、可能性としてまったく同じループで答えました!記憶のために内包表記やフィルターを使用したくない場合、それは非常にPython的な解決策です。