リストから辞書を削除する
質問
もし私が辞書のリストを持っているとしたら、例えば。
[{'id': 1, 'name': 'paul'},
{'id': 2, 'name': 'john'}]
で、辞書を削除したいのですが
id
の2つ(または名前
'john'
を含む)、プログラム的にこれを行う最も効率的な方法は何ですか(つまり、私はリスト内のエントリのインデックスを知らないので、単純にポップすることはできません)。
どのように解決するのですか?
thelist[:] = [d for d in thelist if d.get('id') != 2]
編集
このコードの性能について、コメントでいくつかの疑問が示されているので (Python の性能特性に対する誤解に基づくものと、キー 'id' の値が 2 であるリスト内の dict がちょうど 1 つであると与えられた仕様以上に仮定することによるもの)、この点について安心させてあげたいと思います。
古いLinuxボックスで、このコードを測定します。
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(99)]; import random" "thelist=list(lod); random.shuffle(thelist); thelist[:] = [d for d in thelist if d.get('id') != 2]"
10000 loops, best of 3: 82.3 usec per loop
のうち、random.shuffleに約57マイクロ秒(削除する要素が常に同じ場所にないことを保証するために必要;-)、最初のコピーに0.65マイクロ秒(Pythonリストの浅いコピーによるパフォーマンスの影響を心配している人は、明らかに昼食を取っていない;-)、ループ内の元のリストを変更しないために必要(従ってループの各脚には、削除する何かがある;-)です。
削除するちょうど1つの項目があることが分かっているとき、それを見つけてより迅速に削除することが可能です。
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(99)]; import random" "thelist=list(lod); random.shuffle(thelist); where=(i for i,d in enumerate(thelist) if d.get('id')==2).next(); del thelist[where]"
10000 loops, best of 3: 72.8 usec per loop
(を使用します。
next
ではなく、組み込みの
.next
メソッドではなく) -- しかしこのコードは、削除条件を満たすディクショ ンの数がちょうど1でない場合に破綻します。これを一般化すると、次のようになります。
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*3; import random" "thelist=list(lod); where=[i for i,d in enumerate(thelist) if d.get('id')==2]; where.reverse()" "for i in where: del thelist[i]"
10000 loops, best of 3: 23.7 usec per loop
ここで、シャッフルは削除することができます。なぜなら、すでに知っているように、削除すべき3つの等位なディクショがあるからです。そして、listcompは、変更されずに、うまくいきます。
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*3; import random" "thelist=list(lod); thelist[:] = [d for d in thelist if d.get('id') != 2]"
10000 loops, best of 3: 23.8 usec per loop
は、99のうちたった3つの要素を削除するだけで、完全に首尾一貫しています。より長いリストとより多くの繰り返しで、これはもちろんさらに保持されます。
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*133; import random" "thelist=list(lod); where=[i for i,d in enumerate(thelist) if d.get('id')==2]; where.reverse()" "for i in where: del thelist[i]"
1000 loops, best of 3: 1.11 msec per loop
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*133; import random" "thelist=list(lod); thelist[:] = [d for d in thelist if d.get('id') != 2]"
1000 loops, best of 3: 998 usec per loop
全体として、完全に単純で明白なリスト内包に対して、削除するインデックスのリストを作成し反転させるという繊細さを展開する価値は、1 つの小さなケースで 100 ナノ秒を獲得し、より大きなケースで 113 マイクロ秒を失う可能性が明らかにあります;-) 。シンプルでわかりやすく、完全にパフォーマンスが適切なソリューション (この一般的なクラスの "remove some items from a list" 問題に対するリスト理解など) を回避または批判することは、「早すぎる最適化はプログラミングにおけるすべての悪の根源である」という Knuth と Hoare の有名なテーゼの特にひどい例と言えるでしょう(quot; -quot;)。
関連
-
[解決済み] リストのリストからフラットなリストを作るには?
-
[解決済み] リスト内のアイテムのインデックスを検索する
-
[解決済み] 辞書を値で並べ替えるにはどうしたらいいですか?
-
[解決済み] Pythonで辞書に新しいキーを追加するにはどうすればよいですか?
-
[解決済み] リストが空かどうかを確認するにはどうすればよいですか?
-
[解決済み] Pythonの辞書からキーを削除するにはどうしたらいいですか?
-
[解決済み] 辞書のリストを辞書の値でソートするにはどうしたらいいですか?
-
[解決済み] モジュールの関数名(文字列)を使って、モジュールの関数を呼び出す。
-
[解決済み] インデックスを指定してリストから要素を削除する方法
-
[解決済み] なぜList<T>を継承しないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] PythonでファイルのMD5チェックサムを計算するには?重複
-
[解決済み] pandasのDataFrameから空のセルを含む行を削除する
-
[解決済み] PILからopenCVフォーマットへの変換
-
[解決済み] PythonでSVGからPNGに変換する
-
[解決済み] なぜ(0-6)は-6=偽なのか?重複
-
[解決済み] DataFrameに日付間の日数カラムを追加する pandas
-
[解決済み] PyQtアプリケーションのスレッド化。QtスレッドとPythonスレッドのどちらを使うか?
-
[解決済み] Pandasのデータフレーム内の文字列を'date'データ型に変換するにはどうしたらいいですか?
-
[解決済み] pycharmがタブをスペースに自動変換する
-
[解決済み] データクラスとtyping.NamedTupleの主な使用例