web-dev-qa-db-ja.com

キーごとに複数の値を持つリストから辞書への変換?

キー/値のペアを保持するPythonリストがあります:

l=[ [1, 'A'], [1, 'B'], [2, 'C'] ]

リストをディクショナリに変換します。ディクショナリでは、キーごとに複数の値がタプルに集約されます。

{ 1:('A', 'B'), 2:('C',) }

反復解法は簡単です。

l=[ [1, 'A'], [1, 'B'], [2, 'C'] ]
d={}
for pair in l:
    if d.has_key(pair[0]):
        d[pair[0]]=d[pair[0]]+Tuple(pair[1])
    else:
        d[pair[0]]=Tuple(pair[1])

print d

{1: ('A', 'B'), 2: ('C',)}

このタスクのためのよりエレガントでPython的なソリューションはありますか?

52
Adam Matan
_from collections import defaultdict

d1 = defaultdict(list)

for k, v in l:
    d1[k].append(v)

d = dict((k, Tuple(v)) for k, v in d1.iteritems())
_

dには現在{1: ('A', 'B'), 2: ('C',)}が含まれています

_d1_は、値としてリストを持つ一時的なdefaultdictであり、最終行でタプルに変換されます。このようにして、リストに追加し、メインループでタプルを再作成しません。

51
eumiro

この方法は比較的効率的で非常にコンパクトです。

reduce(lambda x, (k,v): x[k].append(v) or x, l, defaultdict(list))

Python3では、これは次のようになります(エクスポートを明示的にする):

dict(functools.reduce(lambda x, d: x[d[0]].append(d[1]) or x, l, collections.defaultdict(list)))

Reduceはfunctoolsに移動し、ラムダはタプルを受け入れないことに注意してください。このバージョンは2.6および2.7でも動作します。

10
user2085084

Dict値としてタプルの代わりにリストを使用する:

l=[ [1, 'A'], [1, 'B'], [2, 'C'] ]
d={}
for key, val in l:
    d.setdefault(key, []).append(val)

print d
9
Sven Marnach

入力リストでキーがすでにソートされていますか?その場合、機能的な解決策があります。

import itertools

lst = [(1, 'A'), (1, 'B'), (2, 'C')]
dct = dict((key, Tuple(v for (k, v) in pairs)) 
           for (key, pairs) in itertools.groupby(lst, lambda pair: pair[0]))
print dct
# {1: ('A', 'B'), 2: ('C',)}
3
tokland