2016-01-07 9 views
0

В качестве примера я есть словарь следующим образом:Использование словаря значений для расчета суммы взвешенных значений без явно определенных весов

mydict = {A:['asdasd',2,3], B:['asdasd',4,5], C:['rgerg',9,10]} 

Как я могу получить только одно число, которое, по существу, сумма взвешенных значений все ключи в dict (этот пример: A, B, C), взвешенный последним номером в списке (list[-1])?

Так, например, это будет сумма:

(2/15)*3 + (4/15)*5 + (9/15)*10 = 7.73 

где 15 является суммой 2,4,9.

В настоящее время я создаю слишком много переменных, которые просто перебирают словарь. Я уверен, что есть быстрый эффективный способ python.

ответ

2

Используя тот факт, что (2/15)*3 + (4/15)*5 + (9/15)*10 это так же, как (2*3 + 4*5 + 9*10)/15, вы не должны заранее рассчитать общее количество, так что вы могли бы сделать это в один проход Dict с reduce, но, возможно, это ISN» t как читаемый.

Включение Dict в серию кортежей:

>>> d = {A:['asdasd',2,3], B:['asdasd',4,5], C:['rgerg',9,10]} 
>>> from functools import reduce # Py3 
>>> x,y = reduce(lambda t, e: (t[0]+e[0], t[1]+e[1]), ((a*b, a) for _,a,b in d.values())) 
>>> x/y # float(y) in Py2 
7.733333333333333 

Или без промежуточного генератора и используя начальное значение (вероятно, самый быстрый):

>>> x,y = reduce(lambda t, e: (t[0]+e[1]*e[2], t[1]+e[1]), d.values(), (0,0)) 
>>> x/y # float(y) in Py2 
7.733333333333333 

Или вы могли бы застегивать результаты и сумма:

>>> x,y = (sum(x) for x in zip(*((a*b, a) for _,a,b in d.values()))) 
>>> x/y # float(y) in Py2 
7.733333333333333 

Или вы могли бы сделать то, что предлагает @ranlot, хотя я бы избегал i ntermediate lists:

>>> sum(a*b for _,a,b in d.values())/sum(a for _,a,b in d.values()) 
7.733333333333333 

Хотя это кажется менее медленным, чем любой из вышеперечисленных.

+0

Спасибо. Мне очень нравится первый вариант, который вы мне дали. Это был самый быстрый метод с данными, которые я использую. Это то, чем я был после, renlot дал аналогичный подход, который я провел с гораздо более лаконично сделанными. Я повторю свой запрос, который я сделал для renlot. Я создаю словарь на лету для других целей, и я только что добавил эти переменные. Думаете ли вы, что ради спасения нужно что-то другое, кроме как в дикторе? – FancyDolphin

+0

Без каких-либо подробностей трудно сказать, вы могли бы избежать добавления значений в dict, а затем вычислять, просто вычисляя результаты на лету. – AChampion

+0

Из любопытства я играл с ним и не понимал его. Синтаксис мудрый, как бы я, используя ваш метод уменьшения lamdba, включить оператор if, если сказать e [0] == 'asdasd'? – FancyDolphin

1
myDict = {'A':['asdasd', 2, 3], 'B':['asdasd', 4, 5], 'C':['rgerg', 9, 10]} 
normConst = sum([dict[x][-2] for x in myDict]) 
sum([dict[x][-1]*dict[x][-2]/float(normConst) for x in myDict]) 
+0

вы можете использовать 'sum (..)' вместо 'sum ([..])'. Вы можете использовать 'for v в some_dict.values ​​()', чтобы получить значения. Не используйте 'dict' в качестве имени переменной, оно затеняет встроенный. – jfs

+0

Вопрос об этом: С точки зрения скорости, я по-прежнему по существу нуждаюсь в повторении словаря, например, когда я использую iteritems, например. Так как я создаю словарь, должен ли я хранить 2 и 3 в векторе, когда я читаю файл, который создает словарь/список, или есть другой способ, как работающий подсчет, который будет быстрее? – FancyDolphin