簡體   English   中英

根據鍵映射dicts

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM