开发者

What's the most pythonic way to merge 2 dictionaries, but make the values the average values?

开发者 https://www.devze.com 2023-03-19 18:39 出处:网络
d1 = { 开发者_开发知识库\'apples\': 2, \'oranges\':5 } d2 = { \'apples\': 1, \'bananas\': 3 } result_dict = { \'apples\': 1.5, \'oranges\': 5, \'bananas\': 3 }
d1 = { 开发者_开发知识库'apples': 2, 'oranges':5 }
d2 = { 'apples': 1, 'bananas': 3 }


result_dict = { 'apples': 1.5, 'oranges': 5, 'bananas': 3 }

What's the best way to do this?


Here is one way:

result = dict(d2)
for k in d1:
    if k in result:
        result[k] = (result[k] + d1[k]) / 2.0
    else:
        result[k] = d1[k]


This would work for any number of dictionaries:

dicts = ({"a": 5},{"b": 2, "a": 10}, {"a": 15, "b": 4})
keys = set()
averaged = {}
for d in dicts:
    keys.update(d.keys())
for key in keys:
    values = [d[key] for d in dicts if key in d]
    averaged[key] = float(sum(values)) / len(values)
print averaged
# {'a': 10.0, 'b': 3.0}

Update: @mhyfritz showed a way how you could reduce 3 lines to one!

dicts = ({"a": 5},{"b": 2, "a": 10}, {"a": 15, "b": 4})
averaged = {}
keys = set().union(*dicts)
for key in keys:
    values = [d[key] for d in dicts if key in d]
    averaged[key] = float(sum(values)) / len(values)
print averaged


Your question was for the most 'Pythonic' way.

I think for a problem like this, the Pythonic way is one that is very clear. There are many ways to implement the solution to this problem! If you really do have only 2 dicts then the solutions that assume this are great because they are much simpler (and easier to read and maintain as a result). However, it's often a good idea to have the general solution because it means you won't need to duplicate the bulk of the logic for other cases where you have 3 dictionaries, for example.

As an addendum, phant0m's answer is nice because it uses a lot of Python's features to make the solution readable. We see a list comprehension:

[d[key] for d in dicts if key in d]

Use of Python's very useful set type:

keys = set()
keys.update(d.keys())

And generally, good use of Python's type methods and globals:

d.keys()
keys.update( ... )
keys.update
len(values)

Thinking of and implementing an algorithm to solve this problem is one thing, but making it this elegant and readable by utilising the power of the language is what most people would deem 'Pythonic'.

(I would use phant0m's solution)


Yet another way:

result = dict(d1)
for (k,v) in d2.items():
    result[k] = (result.get(k,v) + v) / 2.0


A Counter and some Generators are useful in this situation

General Case:

>>> d1 = { 'apples': 2, 'oranges':5 }
>>> d2 = { 'apples': 1, 'bananas': 3 }
>>> all_d=[d1,d2]
>>> from collections import Counter
>>> counts=Counter(sum((d.keys() for d in all_d),[]))
>>> counts
Counter({'apples': 2, 'oranges': 1, 'bananas': 1})
>>> s=lambda k: sum((d.get(k,0) for d in all_d))
>>> result_set=dict(((k,1.0*s(k)/counts[k]) for k in counts.keys()))
>>> result_set
{'apples': 1.5, 'oranges': 5.0, 'bananas': 3.0}


d1 = { 'apples': 2, 'oranges':5 }
d2 = { 'apples': 1, 'bananas': 3, 'oranges':0 }
dicts = [d1, d2]

result_dict = {}

for dict in dicts:
    for key, value in dict.iteritems():
        if key in result_dict:
            result_dict[key].append(value)
        else:
            result_dict[key] = [value]

for key, values in result_dict.iteritems():
    result_dict[key] = float(sum(result_dict[key])) / len(result_dict[key])

print result_dict
0

精彩评论

暂无评论...
验证码 换一张
取 消