LoginSignup
0
0

リストの辞書が欲しい時とかdefaultdictを使ってみた。

Posted at

今回もまたpythonの小ネタです。というかちょっと調べたら出てきたので書く価値があるか不明ですが、書きます。

やったこと

リストを格納した辞書を作成するために、存在しないキーに勝手に新しいリストを作ってくれる方法を探した。 割と基本的なところにあった。

稀によくある面倒なこと

pythonに限りませんが、リストの辞書が欲しくなることってないですか。何かのコレクションを読み取って、その中の特定の値をキーに読み取った内容を再構成するようなコードを書く時ってあります。実際に書いてみます。

listtodict.py
# 居住地 & 名前のタプルのリスト
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がそのままそれでした。長いので差分だけ書きます。

defdict.py
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の発見を通して、ちゃんとマニュアルを読めという教訓をお伝えしました(ほんとそれだと思う)。

  1. pythonのリファレンスって、縦に長かったり見出しが目立たなかったりして読みづらい。あと例文が解りにくいことがある。

  2. defaultdictはキーが存在しないことに気付かずにデフォルト値を生成してしまう可能性がある、dict.setdefaultは明示的にキーが存在しない可能性を想定して呼び出す。扱うdictの性質で使い分けてもいいかもしれません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0