[英]Mapping dicts based on key
給出一個dict
list
input = [
{'key': k1, 'value': v1},
{'key': k1, 'value': v2},
{'key': k2, 'value': v3}
]
將這些映射到輸出的最簡單方法是什么
output == {k1: (v1, v2), k2: (v3)}
我並不關心價值觀的順序。 我想出的最好的是。
output = dict()
for i in input:
temp = output.get(i['key'], [])
temp.append(i['value'])
output[i['key']] = temp
有什么用dict理解這樣做的嗎? 我假設相同的過程也適用於具有屬性的對象列表。
您可以使用collections.defaultdict
循環遍歷您的詞典值,然后將它們附加到defaultdict
:
>>> from collections import defaultdict
>>> a = defaultdict(tuple)
>>> for d in input:
... a[d['key']] += (d['value'],)
...
>>> a
defaultdict(<type 'tuple'>, {'k2': ('v3',), 'k1': ('v1', 'v2')})
在詞典理解中,任何單個鍵只能被訪問或修改一次。 為了確保多個值與單個鍵配對,則需要預先對這些值進行分組。 天真的分組解決方案最多只能具有二次性能。 事實上,我不能想出一個比立方更好的單線; 這是一個丑陋的野獸,甚至不值得張貼。
因此,基於defaultdict
的方法幾乎總是最好的。
但是,如果您的數據保證排序,或者您願意接受O(n log n)性能,那么您可以使用itertools.groupby
。
>>> input
[{'value': 1, 'key': 'a'}, {'value': 2, 'key': 'a'}, {'value': 3, 'key': 'b'}]
>>> {k:tuple(d['value'] for d in v) for k, v in
... itertools.groupby(input, key=lambda d: d['key'])}
{'a': (1, 2), 'b': (3,)}
要擺脫難看的lambda
,你可以使用operator
。
>>> {k:tuple(d['value'] for d in v) for k, v in
... itertools.groupby(input, key=operator.itemgetter('key'))}
{'a': (1, 2), 'b': (3,)}
或者,如果你必須先排序:
>>> {k:tuple(d['value'] for d in v) for k, v in itertools.groupby(
... sorted(input, key=operator.itemgetter('key')),
... key=operator.itemgetter('key'))}
{'a': (1, 2), 'b': (3,)}
這些解決方案都沒有吸引力; 他們看起來有點像濫用理解語法,可能除了第二個。
作為從collections
導入的替代方法,您可以使用setdefault
- 盡管這會生成列表而不是元組:
>>> output = {}
>>> for d in input:
... output.setdefault(d['key'], []).append(d['value'])
...
>>> output
{'a': [1, 2], 'b': [3]}
最后,考慮這個替代方案 - 我不知道我對它的感受,但它確實避免了所有導入和異國情調的功能,並產生元組:
>>> output = {d['key']:() for d in input}
>>> for d in input:
... output[d['key']] += (d['value'],)
...
>>> output
{'a': (1, 2), 'b': (3,)}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.