12

辞書のリストが 2 つあります (Django クエリセットとして返されます)。各ディクショナリには ID 値があります。ID 値に基づいて、2 つを 1 つの辞書リストにマージしたいと思います。

例えば:

list_a = [{'user__name': u'Joe', 'user__id': 1},
          {'user__name': u'Bob', 'user__id': 3}]
list_b = [{'hours_worked': 25, 'user__id': 3},
          {'hours_worked': 40, 'user__id': 1}]

そして、私は関数が生成することを望みます:

list_c = [{'user__name': u'Joe', 'user__id': 1, 'hours_worked': 40},
          {'user__name': u'Bob', 'user__id': 3, 'hours_worked': 25}]

その他の注意事項:

  • リスト内の ID は、同じ順序ではない場合があります (上記の例のように)。
  • リストにはおそらく同じ数の要素がありますが、そうでない場合はオプションを説明したいと思いますが、list_a からのすべての値を保持します (本質的にlist_a OUTER JOIN list_b USING user__id)。
  • SQL でこれを実行しようとしましたが、一部の値が一部の除外に基づく集計であるため、不可能です。
  • user__id使用されるデータベース クエリにより、各リストに同じ辞書が多くても 1 つしか存在しないと想定しても問題ありません。

お時間をいただきありがとうございました。

4

2 に答える 2

19

itertools.groupby要素をグループ化するために使用します。

lst = sorted(itertools.chain(list_a,list_b), key=lambda x:x['user__id'])
list_c = []
for k,v in itertools.groupby(lst, key=lambda x:x['user__id']):
    d = {}
    for dct in v:
        d.update(dct)
    list_c.append(d)
    #could also do:
    #list_c.append( dict(itertools.chain.from_iterable(dct.items() for dct in v)) )
    #although that might be a little harder to read.

lambda関数に嫌悪感がある場合は、operator.itemgetter('user__id')代わりにいつでも使用できます。(おそらくもう少し効率的です)

lambda/itemgetter を少しわかりやすくするために、次の点に注意してください。

def foo(x):
    return x['user__id']

は、次のいずれかと同じです*:

foo = operator.itemgetter('user__id')
foo = lambda x: x['user__id']

*いくつかの違いがありますが、この問題では重要ではありません

于 2012-12-20T15:10:36.813 に答える
6
from collections import defaultdict
from itertools import chain

list_a = [{'user__name': u'Joe', 'user__id': 1},
      {'user__name': u'Bob', 'user__id': 3}]
list_b = [{'hours_worked': 25, 'user__id': 3},
      {'hours_worked': 40, 'user__id': 1}]

collector = defaultdict(dict)

for collectible in chain(list_a, list_b):
    collector[collectible['user__id']].update(collectible.iteritems())

list_c = list(collector.itervalues())

ご覧のとおり、これは別の dict を使用して既存の dict をマージするだけです。defaultdict の秘訣は、新しいエントリの dict を作成するという骨の折れる作業を取り除くことです。

これらの入力をグループ化またはソートする必要はありません。dict はそのすべてを処理します。

真の防弾ソリューションは、入力に「user__id」キーがない場合に潜在的なキーエラーをキャッチするか、デフォルト値を使用してそのようなキーなしですべての辞書を収集します。

于 2012-12-20T15:43:38.210 に答える