Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
101
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

dictで一つのキーに複数の値を持ちたい時の実装方法

この記事は Pythonのコードを短く簡潔に書くテクニック Advent Calendar 2017 の4日目です。

はじめに

dictで一つのキーに複数の値を持つために値をリストにすることがあります。
この時、データを挿入していくには既に値があるかチェックし、なければ空のリストを挿入する、という操作が必要になります。

こういった操作をするのに便利なやり方をいくつか紹介します。

例題

単語が入ったリストから、頭文字をキーとしたdictに格納する処理を考えてみます。

元データの単語リスト
words = ['apple', 'orange', 'banana', 'alpha', 'beta']

欲しい結果
results = {
    'a': ['apple', 'alpha'],
    'b': ['banana', 'beta'],
    'o': ['orange'],
}

普通に書いた場合

results = {}
for word in words:
    key = word[0]
    if key not in results:    #1
        results[key] = []     #2
    results[key].append(word) #3

普通に書くと、1.キーの存在チェック、2.空リストの作成、3.リストに単語を格納、の3回もdictにアクセスしなければなりません。
コードも長くなります。

dict.setdefault()を使う

setdefault()はdictから値を取得する際に指定のキーがなければデフォルト値を設定してくれます。

results = {}
for word in words:
    results.setdefault(word[0], []).append(word)

これを使うとコードがスッキリする上に、dictへのアクセスが1回で済むようになります。

collections.defaultdictを使う

defaultdictでも同じようなことができます。
コンストラクタでデフォルト値を作成する関数を指定します。
[]でキーを参照したときに、なければデフォルト値が設定されます。

from collections import defaultdict

results = defaultdict(list)
for word in words:
    results[word[0]].append(word)

itertools.groupbyを使う

groupbyを使うとリストを任意のキーでグルーピングできます。
この結果で辞書を作成すれば目的の結果が得られます。
ただしgroupbyに渡すリストは事前にソートする必要があります。

from itertools import groupby
from operator import itemgetter

results = {k: list(v)
           for k, v in groupby(sorted(words), key=itemgetter(0))}

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
101
Help us understand the problem. What are the problem?