Edited at

Python の辞書で条件に一致するキーと値を削除する


お題

辞書で特定のキーを持つ要素を除くケースを考える。ただし、次の条件をどちらも満たしている。


  • 辞書の中身が事前に分からない

  • 対象のキーは 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)