4

Python でリストの最後の要素を削除しようとしています:

di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
for el in di['children']:
  di['children'].remove(el)

私が期待するのは

print di
{'a': 3, 'children: []}

しかし、私が得るのは

print di
{'a': 3, 'children': [{'c': 6}]}

何がうまくいかないのか誰にも分かりますか?

4

7 に答える 7

11

他の人が説明したように、リストを反復処理中にリストを変更することはできません。

リストのコピーを繰り返し処理しながらリストを変更することはできますが、新しいフィルタリングされたリストを生成する方がおそらく良いでしょう:

di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
di['children'] = [el for el in di['children'] if el not in di['children']]

なぜこれが良いのですか?これは、リストの変更を回避していることを意味します。これにより、コードの推論が容易になり、トレースが容易になり、通常は記述が容易になり、多くの場合、高速でスペース効率が向上します。反復中の変更の問題を心配する必要がないという事実は、「推論が容易」な部分の完璧な例です。

場合によっては、書くのが難しくなったり、遅くなったり、スペース効率が悪くなったりすることがあります。そのため、これは厳密なルールではなく単なるガイドラインです。しかし、答えが「いいえ」であることが判明したとしても、少なくとも「これをミューテーターではなく不変フィルターとして書き直すことはできますか」と考える価値は常にあります。

また、本当に、あなたのアルゴリズムはすべてを空にするのと同等であることが保証されていませんか? その場合:

di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
di['children'] = []
于 2012-10-30T22:42:56.753 に答える
6

リストを反復するときにリストを変更しないでください。代わりに、コピーを反復処理する必要があります。python docsを参照してください。

これを試して...

di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
for el in di['children'][:]:
    di['children'].remove(el)
于 2012-10-30T22:37:29.087 に答える
6

リストを反復しながらリストを変更しています。最初のエントリを削除すると、2 番目のエントリが最初のエントリになり、リストの最後に到達します。代わりに、次を使用します。

del di["children"][:]

これにより、元のリストが保持されるため ( とは異なりdi["children"] = [])、それらへの他の参照がある場合は、切り捨ても反映されます。

于 2012-10-30T22:40:08.820 に答える
4

逆方向にリストを通過する場合、ループ内の要素のみを削除できます。

したがって、このように di['children'] を reversed() イテレータでラップするだけだと思います

for el in reversed(di['children']):

これは、要素を削除すると要素の数が変化し、後続のすべての要素の番号が 1 を引いた値になるためです。しかし、逆に考えると、後続の要素のインデックスは気にする必要はなく、削除する前の要素だけを気にする必要があります。

于 2012-10-30T22:44:02.170 に答える
2
del di['children'][1]

リストの最後の要素を削除します。

于 2012-11-01T21:06:32.727 に答える
2

リストを繰り返し処理しながらリストを変更していますが、これは悪い考えです。

元の要素を削除しながら、リストのコピーを反復処理してみてください。

于 2012-10-30T22:38:06.573 に答える
0
 for i in di:
    if type(di[i])==list:
       di[i]=[]
于 2012-10-31T14:21:16.300 に答える