お題
辞書で特定のキーを持つ要素を除くケースを考える。ただし、次の条件をどちらも満たしている。
- 辞書の中身が事前に分からない
- 対象のキーは
two
だが、大文字小文字を区別しない
例えば次のような結果となる。
import pprint
dic = {'one': 1, 'two': 2, 'three': 3}
# 削除処理
# pprint.pprint(dic)
# => {'one': 1, 'three': 3}
dic = {'one': 1, 'TWO': 2, 'three': 3}
# 削除処理
# pprint.pprint(dic)
# => {'one': 1, 'three': 3}
dic = {'one': 1, 'Two': 2, 'three': 3}
# 削除処理
# pprint.pprint(dic)
# => {'one': 1, 'three': 3}
次の記述でOK
dic = {k: v for k, v in dic.items() if k.lower() != 'two'}
# pprint.pprint(dic)
# => {'one': 1, 'three': 3}
イテレータを使う場合は Python 2.x と 3.x の互換性を考慮して six を使う事を検討したい。
import six
dic = {k: v for k, v in six.iteritems(dic) if k.lower() != 'two'}
# pprint.pprint(dic)
# => {'one': 1, 'three': 3}
リスト内包表記を使用しない場合は要注意
リスト内包表記を使用しない場合、次の記述で良さそうに思える。
for k, v in dic.items():
if k.lower() == 'two':
dic.pop(k, None)
Python 2.x では問題ないが、Python 3.x では次のエラーが発生する。
Traceback (most recent call last):
File "delete_if.py", line 4, in <module>
for k, v in dic.items():
RuntimeError: dictionary changed size during iteration
代わりに次のように記述する。
for k, v in list(dic.items()):
if k.lower() == 'two':
dic.pop(k, None)
値は取り出しても参照しないのであれば、次の記述の方がシンプルになる。
for k in list(dic.keys()):
if k.lower() == 'two':
dic.pop(k, None)
さらにイテレータを使う場合は次のようになる。
import six
for k in list(six.iterkeys(dic)):
if k.lower() == 'two':
dic.pop(k, None)