home changes contents help options

119:1つのキーに複数の値が対応するハッシュを作る

Ruby のハッシュの役割をする Python の型は 辞書 です。辞書の値は一つのキーあたり一つなので、実際には複数の値は入りません。複数の値が入っているように見せるには辞書の値をリストにし、そのリストに値を追加するとよいでしょう。

>>> d = {}
>>> d['a'] = []
>>> d['a'].append(1)
>>> d['a'].append(2)
>>> d['a'].append(3)
>>> d['b'] = []
>>> d['b'].append(4)
>>> d['b'].append(5)
>>> d
{'a': [1, 2, 3], 'b': [4, 5]}

とはいえ、「リストを含む辞書を作る」という簡単なはずの目的に対して、それを実現する手段が「リストを用意して」、「値を入れる」、という 2 つに分かれてしまっていてはコードが煩雑になりがちです。 setdefault メソッドを使うともう少しスマートに書き表せます。

>>> d = {}
>>> d.setdefault('a', []).append(1)
>>> d.setdefault('a', []).append(2)
>>> d.setdefault('a', []).append(3)
>>> d.setdefault('b', []).append(4)
>>> d.setdefault('b', []).append(5)
>>> d
{'a': [1, 2, 3], 'b': [4, 5]}

これならば場合分けすることなく、ループで処理することができます。

>>> d = {}
>>> keys = ['a', 'b']
>>> values = ((1, 2, 3), (4,5))
>>> for key, values2 in zip(keys, values):
...   for value in values2:
...     d.setdefault(key, []).append(value)
...
>>> d
{'a': [1, 2, 3], 'b': [4, 5]}

同様の方法で辞書を含む辞書を作ることもできます。こちらのほうが便利であることもあります。

>>> d = {}
>>> d.setdefault('a', {})['aa'] = 1
>>> d.setdefault('a', {})['bb'] = 2
>>> d.setdefault('a', {})['cc'] = 3
>>> d.setdefault('b', {})['dd'] = 4
>>> d.setdefault('b', {})['ee'] = 5
>>> d
{'a': {'aa': 1, 'cc': 3, 'bb': 2}, 'b': {'ee': 5, 'dd': 4}}

Python 2.5 以降ならば、 collections の defaultdict クラスを使用することができます。

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d['a'].append(1)
>>> d['a'].append(2)
>>> d['a'].append(3)
>>> d['b'].append(4)
>>> d['b'].append(5)
>>> d
defaultdict(<type 'list'>, {'a': [1, 2, 3], 'b': [4, 5]})