キー/値のペアを保持する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的なソリューションはありますか?
_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であり、最終行でタプルに変換されます。このようにして、リストに追加し、メインループでタプルを再作成しません。
この方法は比較的効率的で非常にコンパクトです。
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でも動作します。
Dict値としてタプルの代わりにリストを使用する:
l=[ [1, 'A'], [1, 'B'], [2, 'C'] ]
d={}
for key, val in l:
d.setdefault(key, []).append(val)
print d
入力リストでキーがすでにソートされていますか?その場合、機能的な解決策があります。
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',)}