2009-06-06 21 views
167

値がリストである辞書を作成したいと思います。たとえば、次のようにリストの辞書を作成するPython

{ 
    1: ['1'], 
    2: ['1','2'], 
    3: ['2'] 
} 

私が行う場合:dは[...]リストではありませんので、

d = dict() 
a = ['1', '2'] 
for i in a: 
    for j in range(int(i), int(i) + 2): 
     d[j].append(i) 

私は、KeyError例外を取得します。この場合、辞書を初期化するためにaを代入した後、次のコードを追加することができます。

for x in range(1, 4): 
    d[x] = list() 

これを行うより良い方法はありますか?私が2番目のforループに入るまで、私が必要とする鍵がわからないと言います。たとえば:?

class relation: 
    scope_list = list() 
... 
d = dict() 
for relation in relation_list: 
    for scope_item in relation.scope_list: 
     d[scope_item].append(relation) 

代替は、これを処理するための最良の方法は何ですか

if d.has_key(scope_item): 
    d[scope_item].append(relation) 
else: 
    d[scope_item] = [relation,] 

d[scope_item].append(relation) 

を交換することになりますか理想的には、追加することは「うまくいく」でしょう。リストを最初に作成したときにすべてのキーがわからなくても、空リストの辞書を欲しいと表現する方法はありますか?

答えて

211

は、あなたが使うことができdefaultdict

>>> from collections import defaultdict 
>>> d = defaultdict(list) 
>>> for i in a: 
... for j in range(int(i), int(i) + 2): 
...  d[j].append(i) 
... 
>>> d 
defaultdict(<type 'list'>, {1: ['1'], 2: ['1', '2'], 3: ['2']}) 
>>> d.items() 
[(1, ['1']), (2, ['1', '2']), (3, ['2'])] 
+0

'collections'モジュールの下にある他の辞書も' collections.OrderedDict'のようにこのように動作します。 – txsaw1

+1

ああ。これは素晴らしい。そして、 '= []'に初期化する必要はありません。いい物! –

21

使用setdefault

d = dict() 
a = ['1', '2'] 
for i in a: 
    for j in range(int(i), int(i) + 2): 
     d.setdefault(j, []).append(i) 

print d # prints {1: ['1'], 2: ['1', '2'], 3: ['2']} 

かなり奇妙な名前のsetdefault機能は、「このキーと値を取得、またはそのキーが存在しない場合は、この値を追加し、それを返す。」と言います

編集:他の人が正しく指摘しているように、defaultdictはより良い、より現代的な選択です。 setdefaultはPythonの古いバージョン(2.5より前)でもまだ役に立ちます。

+2

これはうまくいきますが、通常はdefaultdictを使用することをお勧めします。 –

+0

@David、ええ、setdefaultはデザインの中で最も鮮やかなビットではありませんでした。残念ながら、これは決して最良の選択です。私は私たち(Pythonコミッター)がcollects.defaultdictを使って私たちの集団的評判を買収したと思います。 –

+0

@DavidZ、setdefaultはdefaultdictとは異なり、より柔軟です:otherwhise、別の辞書キーに異なるデフォルト値をどうやって指定しますか? –

37

あなたは、このようなリスト内包でそれを構築することができます:

>>> dict((i, range(int(i), int(i) + 2)) for i in ['1', '2']) 
{'1': [1, 2], '2': [2, 3]} 

そして、あなたの質問の後半部分のためdefaultdict

>>> from collections import defaultdict 
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)] 
>>> d = defaultdict(list) 
>>> for k, v in s: 
     d[k].append(v) 

>>> d.items() 
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])] 
1

あなたの質問はすでに回答されていますが、IIRCではliを置き換えることができます、その建設にd参照d.keys()ある

if scope_item in d: 

:と

if d.has_key(scope_item): 

:ようファミコン。時にはdefaultdictが最良の選択肢ではない場合があります(たとえば、上記のifに関連付けられたelseの後に複数行のコードを実行する場合)。inの構文が読みやすくなります。