リスト内のアイテムが存在する場合、それを削除するにはどうすればよいですか? 質問する

リスト内のアイテムが存在する場合、それを削除するにはどうすればよいですか? 質問する

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_tagsnew_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

なぜこのようなことが起こるのでしょうか? また、どうすれば回避できるのでしょうか?

ベストアンサー1

1) ほぼ英語風:

演算子を使用して存在をテストしinremoveメソッドを適用します。

if thing in some_list: some_list.remove(thing)

メソッドは、の代わりに使用できるすべての出現を削除するために、removeの最初の出現のみを削除します。thingwhileif

while thing in some_list: some_list.remove(thing)    
  • 十分シンプルで、おそらく私の選択です。小さなリストの場合(ワンライナーには抵抗できません)

2)ダックタイプEAFPスタイル:

この「最初に撃って最後に質問する」という姿勢は、Python では一般的です。オブジェクトが適切かどうかを事前にテストするのではなく、操作を実行して関連する例外をキャッチするだけです。

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!")

もちろん、上記の例の 2 番目の except 節は、ユーモアとして疑わしいだけでなく、まったく不要です (その目的は、ダックタイピングの概念に馴染みのない人々のために、ダックタイピングを説明することでした)。

複数の事象が発生すると予想される場合:

while True:
    try:
        some_list.remove(thing)
    except ValueError:
        break
  • この特定のユースケースでは少し冗長ですが、Python では非常に慣用的です。
  • これは#1よりもパフォーマンスが良い
  • ペップ463ここで便利な、try/except の簡単な使用法のための短い構文を提案しましたが、承認されませんでした。

しかし、contextlib の suspend() コンテキストマネージャ(Python 3.4 で導入) 上記のコードは次のように簡略化できます。

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

繰り返しますが、thing が複数回発生することが予想される場合は、次のようになります。

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

3) 機能的なスタイル:

1993年頃、Pythonは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、最初の引数として None を渡すことができます:

cleaned_list = filter(None, some_list)
  • [更新] : Python 2.x では、は(または最初の引数が)filter(function, iterable)と同等でしたが、Python 3.x では と同等になりました。微妙な違いは、filter は以前はリストを返していましたが、現在はジェネレータ式のように動作するということです。これは、クリーンアップされたリストを反復処理して破棄するだけであれば問題ありませんが、本当にリストが必要な場合は、呼び出しをコンストラクターで囲む必要があります。[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()
  • *これらのLisp風の構造はPythonでは少々異質だと考えられています。2005年頃、グイドはドロップすることさえ話していたfilter- 仲間たちと一緒にmapreduce彼らはまだ去っていませんがreduce関数ツールモジュールは一見の価値があります高階関数)。

4) 数学的なスタイル:

リストの内包表記Pythonのバージョン2.0で導入されて以来、リスト操作の推奨スタイルとなった。ペップ202map()その背後にある理論的根拠は、リストの内包表記が、現在およびfilter()/またはネストされたループが使用されている状況で、リストを作成するためのより簡潔な方法を提供するという点です。

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

ジェネレータ式はバージョン2.4で導入されました。ペップ289ジェネレータ式は、メモリ内に完全なリストを作成する必要がない(またはしたくない)状況に適しています。たとえば、一度に1つの要素を反復処理したい場合などです。リストを反復処理するだけの場合は、ジェネレータ式を次のように考えることができます。怠惰な評価リストの理解:

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

ノート

  1. !=代わりに不等号演算子を使用するとよいでしょうis notその違いは重要だ
  2. リストのコピーを暗示するメソッドを批判する人へ: 一般的な考えに反して、ジェネレータ式は必ずしもリストの内包表記よりも効率的であるとは限りません。文句を言う前にプロファイルを作成してください。

おすすめ記事