如何根据权重合并字典?

2 投票
5 回答
817 浏览
提问于 2025-04-16 21:34
d1 = {'weight':1, 'data': { 'apples': 8, 'oranges': 7 } }
d2 = {'weight':3, 'data': { 'apples': 4, 'bananas': 3 } }
all_dictionaries = [d1, d2, ... ]

def mergeDictionariesWithWeight(all_dictionaries)

我该如何把这些字典合并在一起(如果有重叠,就用权重来计算多个值)

这个函数会返回:

{ 'apples': 4, 'oranges': 7, 'bananas': 3 }

苹果的值是 4,因为 8 * .25 + 4 * .75

补充:我刚写了一个计算平均值的函数,类似这样。但当然这和我想做的真的很不一样,因为我把所有东西放在一个列表里,然后只是除以长度。

result = {}
keymap = {}
for the_dict in dlist:
    for (k, v) in the_dict.items():
        if not keymap.has_key(k):
            keymap[k] = []
        keymap[k].append(v)
for (k, v) in keymap.items():
    average = sum(int(x) for x in keymap[k]) / float(len(keymap[k]))
    result[k] = float(average)
return result

5 个回答

1
from collections import defaultdict

def merge_dictionaries_with_weight(all_dictionaries):
    totals = defaultdict(int)
    result = defaultdict(int)
    for each in all_dictionaries:
        weight = float(each['weight'])
        for key, value in each['data'].items():
            totals[key] += weight
            result[key] += weight * value
    for key, total in totals.items():
       result[key] /= total
    return result

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言进行解释。

1

这里有一个解决方案,它首先使用一个临时的字典把项目收集到一个列表中,然后再计算出最终的加权字典。其实可以不使用临时字典,但这样做更容易理解。

from collections import defaultdict

def mergeDictionariesWithWeight(dlist):
    tmp = defaultdict(list)
    for d in dlist:
        weight = d['weight']
        for k, v in d['data'].items():
            tmp[k].append((weight, v))
    r = {}
    for k, v in tmp.items():
        # If there's just one item, ignore the weight
        if len(v) == 1:
            r[k] = v[0][1]
        else:
            total_weight = sum((x[0] for x in v), 0.0)
            r[k] = sum(x[1] * x[0]/total_weight for x in v)
    return r

返回的结果是:{'apples': 5.0, 'oranges': 7, 'bananas': 3}(因为 8 * 0.25 + 4 * 0.75 = 5.0)

7
>>> from collections import defaultdict
>>> d=defaultdict(lambda:(0,0))
>>> for D in all_dictionaries:
...   weight = D['weight']
...   for k,v in D['data'].items():
...     d[k]=d[k][0]+weight*v,d[k][1]+weight
... 
>>> dict((k,v[0]/v[1]) for k,v in d.items())
{'apples': 5, 'oranges': 7, 'bananas': 3}

如果你需要浮点数结果

>>> dict((k,1.*v[0]/v[1]) for k,v in d.items())
{'apples': 5.0, 'oranges': 7.0, 'bananas': 3.0}

关于 defaultdict 的说明

你经常会看到 defaultdict(int)defaultdict(list),甚至可能还有 defaultdict(set)。传给 defaultdict 的参数必须是一个不带参数的可调用对象。调用这个参数的结果会在找不到某个键时使用。也就是说,调用这个参数会返回字典的 默认值

举个例子

>>> d=defaultdict(int)
>>> d[1]
0
>>> d['foo']
0

这通常用来计数,因为 int() 会返回 0。如果你想让默认值变成 1 而不是 0,那就有点麻烦,因为你不能给 int 传参数,但你只需要一个返回 1 的可调用对象。使用 lambda 函数就可以轻松做到这一点。

>>> d=defaultdict(lambda:1)
>>> d[1]
1
>>> d['foo']
1

在这个回答中,我想记录加权总和和权重的总和。我可以通过使用一个 2 元组作为默认值来实现。

>>> d=defaultdict(lambda:(0,0))
>>> d[1]
(0, 0)
>>> d['foo']
(0, 0)

撰写回答