今回もまたpythonの小ネタです。というかちょっと調べたら出てきたので書く価値があるか不明ですが、書きます。
やったこと
リストを格納した辞書を作成するために、存在しないキーに勝手に新しいリストを作ってくれる方法を探した。 割と基本的なところにあった。
稀によくある面倒なこと
pythonに限りませんが、リストの辞書が欲しくなることってないですか。何かのコレクションを読み取って、その中の特定の値をキーに読み取った内容を再構成するようなコードを書く時ってあります。実際に書いてみます。
# 居住地 & 名前のタプルのリスト
SOURCE = [
('埼玉県','タケシ,'),
('東京都','ヤスシ,'),
('千葉県','ヒロシ,'),
('埼玉県','ケン'),
('埼玉県','ハルト'),
('埼玉県','アキラ'),
('東京都','ゴロウ'),
('群馬県','ヨシオ'),
('千葉県','カツオ'),
('群馬県','ヒロカズ'),
]
# 結果格納用辞書
meibo = {}
# 各県ごとに辞書に格納
for ken, name in SOURCE:
if ken not in meibo:
# 新しいリストを作る(ここが無駄)
meibo[ken] = []
meibo[ken].append(name)
# まとめた結果を出力
for k, v in meibo.items():
print(k, v)
これで、こんな出力が欲しい。
埼玉県 ['タケシ,', 'ケン', 'ハルト', 'アキラ']
東京都 ['ヤスシ,', 'ゴロウ']
千葉県 ['ヒロシ,', 'カツオ']
群馬県 ['ヨシオ', 'ヒロカズ']
このif ken not in meibo:
相当のコードを色々な言語で何回書いただろう。こんなことpythonなら勝手にやってくれるクラスとかないのか? ちゃんとあった。何してんだ俺は。
defaultdictってちゃんと既にあった
さすpython、collections.defaultdict
がそのままそれでした。長いので差分だけ書きます。
import collections
(略)
# リストのコンストラクタを渡す
meibo = collections.defaultdict(list)
# 各県ごとに辞書に格納
for ken, name in SOURCE:
# kenが存在しなければlist()が呼ばれて格納される
meibo[ken].append(name)
あっさり解決したじゃん。リファレンスマニュアル読めば書いてあるじゃん! 許してくれ俺は仕事でpython使う機会がないんだ・・・という言い訳はさておき、pythonのマニュアルは少々読みにくいので、つい横着に片付けてしまいがち。きっと僕の他にも同じ人がいるはず。1
これもマニュアルに書いてありますが、defaultdict
を使うまでもなく標準のdict
でこうすることもできます。
meibo.setdefault(ken, []).append(name)
しかし、こっちの方法だとsetdefault
が呼び出される時点でリストのインスタンスが作成されてしまう。マニュアルでもこっちだと遅くなると書いてありますが、他の理由として意識的にsetdefault
を呼ぶことに意味があるかどうかで使い分けてもいいと思う。2
以上。dict
に存在しないキーを勝手に生成してくれるdefaultdict
の発見を通して、ちゃんとマニュアルを読めという教訓をお伝えしました(ほんとそれだと思う)。