「RuntimeError:辞書が繰り返し中にサイズを変更した」というエラーを回避するにはどうすればよいですか?
私は他のすべての質問を同じエラーでチェックしましたが、役に立つ解決策は見つかりませんでした= /
リストの辞書があります。
d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}
一部の値が空です。これらのリストを作成し終わったら、辞書を返す前にこれらの空のリストを削除したいと思います。現在私は次のようにこれをやろうとしています:
for i in d:
if not d[i]:
d.pop(i)
しかし、これは私にランタイムエラーを与えています。私はあなたがそれを通して反復している間あなたが辞書の要素を追加/削除することができないことを知っています...その時何を回避するだろうか?
Python 2.xでは、keys
を呼び出すと、dict
を変更しながら繰り返し処理できるキーのコピーが作成されます。
for i in d.keys():
keys
はリストではなくイテレータを返すため、これはPython 3.xでは機能しません。
別の方法は、キーのコピーを作成するためにlist
を使用することです。これはPython 3.xでも動作します。
for i in list(d):
関連項目を新しい辞書にコピーするには、辞書の内包表記を使用するだけです。
>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = { k : v for k,v in d.iteritems() if v}
>>> d
{'a': [1], 'b': [1, 2]}
あなたは "コピー"を使用する必要があります。
そうすれば、元の辞書フィールドを繰り返し処理して、その場で目的の辞書(d dict)を変更できます。これは各Pythonバージョンで動作するので、より明確です。
In [1]: d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}
In [2]: for i in d.copy():
...: if not d[i]:
...: d.pop(i)
...:
In [3]: d
Out[3]: {'a': [1], 'b': [1, 2]}
最初に空のリストを挿入しないようにしますが、通常は次のようにします。
d = {k: v for k,v in d.iteritems() if v} # re-bind to non-empty
2.7より前の場合:
d = dict( (k, v) for k,v in d.iteritems() if v )
あるいは単に:
empty_key_vals = list(k for k in k,v in d.iteritems() if v)
for k in empty_key_vals:
del[k]
Python 3の場合:
{k:v for k,v in d.items() if v}
Forループ中に辞書を変更しながら、辞書を反復処理することはできません。リストにキャストしてそのリストを反復処理すると、私にとってはうまくいきます。
for key in list(d):
if not d[key]:
d.pop(key)
このような状況では、私はオリジナルの辞書を変更しながらディープコピーを作成し、そのコピーをループするのが好きです。
ルックアップフィールドがリスト内にある場合は、リストのforループで列挙してから元の辞書のフィールドにアクセスするための位置をインデックスとして指定できます。
実行時エラーの原因は、データ構造が反復中に変更されている間はデータ構造を反復処理できないことです。
あなたが探しているものを達成するための1つの方法はあなたが削除したいキーを追加するためにリストを使用してからリストを反復しながら識別されたキーを削除するために辞書のpop関数を使用することです。
d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}
pop_list = []
for i in d:
if not d[i]:
pop_list.append(i)
for x in pop_list:
d.pop(x)
print (d)