Какой самый питонный способ объединить 2 словаря, но сделать значения средними? - PullRequest
5 голосов
/ 13 июля 2011
d1 = { 'apples': 2, 'oranges':5 }
d2 = { 'apples': 1, 'bananas': 3 }


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

Какой лучший способ сделать это?

Ответы [ 6 ]

7 голосов
/ 13 июля 2011

Вот один из способов:

result = dict(d2)
for k in d1:
    if k in result:
        result[k] = (result[k] + d1[k]) / 2.0
    else:
        result[k] = d1[k]
6 голосов
/ 13 июля 2011

Это будет работать для любого количества словарей:

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}

Обновление : @mhyfritz показал, как можно сократить 3 строки до одной!

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
3 голосов
/ 13 июля 2011

Ваш вопрос был о наиболее "питонском" способе.

Я думаю, что для такой проблемы Питоновский путь очень ясен. Есть много способов реализовать решение этой проблемы! Если у вас действительно есть только 2 диктанта, то решения, которые предполагают, что это замечательно, потому что они намного проще (и в результате их легче читать и поддерживать). Однако часто бывает полезно иметь общее решение, потому что это означает, что вам не нужно дублировать основную логику для других случаев, когда у вас есть 3 словаря, например.

Как дополнение, ответ phant0m хорош, потому что он использует множество функций Python, чтобы сделать решение читабельным. Мы видим понимание списка:

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

Использование Python очень полезно set тип:

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

И вообще, хорошее использование методов и глобалов типа Python:

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

Думать и реализовывать алгоритм для решения этой проблемы - это одно, но сделать его таким элегантным и читаемым, используя мощь языка, - это то, что большинство людей сочло бы «питонским».

(я бы использовал решение phant0m)

2 голосов
/ 13 июля 2011

Еще один способ:

result = dict(d1)
for (k,v) in d2.items():
    result[k] = (result.get(k,v) + v) / 2.0
0 голосов
/ 13 июля 2011
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 голосов
/ 13 июля 2011

Счетчик и некоторые генераторы полезны в этой ситуации

Общий случай:

>>> 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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...