2

I've following nested dictionary, where the first number is resource ID (the total number of IDs is greater than 100 000):

dict = {1: {'age':1,'cost':14,'score':0.3},
        2: {'age':1,'cost':9,'score':0.5},
        ...}

I want to add to each resource a sum of costs of resources with lower score than given resource. I can add 'sum_cost' key which is equal to 0 by following code:

for id in adic:
    dict[id]['sum_cost'] = 0

It gives me following:

dict = {1: {'age':1,'cost':14,'score':0.3, 'sum_cost':0},
        2: {'age':1,'cost':9,'score':0.5,'sum_cost':0},
        ...}

Now I would like to use ideally for loop (to make the code easily readable) to assign to each sum_cost a value equal of sum of cost of IDs with lower score than the given ID.

Ideal output looks like dictionary where 'sum_cost' of each ID is equal to the cost of IDs with lower score than given ID:

dict = {1: {'age':1,'cost':14,'score':0.3, 'sum_cost':0},
        2: {'age':1,'cost':9,'score':0.5,'sum_cost':21},
        3: {'age':13,'cost':7,'score':0.4,'sum_cost':14}}

Is there any way how to do it?

2 Answers2

4

Notes:

Using sorted method for sorting the dictionary output corresponding to the key score

dictionary get method to get dictionary values

and using a temporary variable for cumulative addition os sum_cost

Code:

dicts = {1: {'age': 1, 'cost': 14, 'score': 0.3, 'sum_cost': 0},
         2: {'age': 1, 'cost': 9, 'score': 0.5, 'sum_cost': 0},
         3: {'age': 13, 'cost': 7, 'score': 0.4, 'sum_cost': 0}}

sum_addition = 0

for key, values in sorted(dicts.items(), key=lambda x: x[1].get('score', None)):
    if dicts[key].get('score') is not None: #By default gives None when key is not available
        dicts[key]['sum_cost'] = sum_addition
        sum_addition += dicts[key]['cost']
        print key, dicts[key]

A even more simplified method by @BernarditoLuis and @Kevin Guan advise

Code2:

dicts = {1: {'age': 1, 'cost': 14, 'score': 0.3, 'sum_cost': 0},
         2: {'age': 1, 'cost': 9, 'score': 0.5, 'sum_cost': 0},
         3: {'age': 13, 'cost': 7, 'score': 0.4, 'sum_cost': 0}}

sum_addition = 0

for key, values in sorted(dicts.items(), key=lambda x: x[1].get('score', None)):
    if dicts[key].get('score'): #By default gives None when key is not available
        dicts[key]['sum_cost'] = sum_addition
        sum_addition += dicts[key]['cost']
        print key, dicts[key]

Output:

1 {'sum_cost': 0, 'age': 1, 'cost': 14, 'score': 0.3}
3 {'sum_cost': 14, 'age': 13, 'cost': 7, 'score': 0.4}
2 {'sum_cost': 21, 'age': 1, 'cost': 9, 'score': 0.5}
Community
  • 1
  • 1
The6thSense
  • 8,103
  • 8
  • 31
  • 65
  • 1
    I think you don't need use `if dicts[key].get('score', False) != False:` here, what about just `if dicts[key].get('score', False):`? :) – Remi Guan Nov 03 '15 at 09:48
  • @KevinGuan that would do but just wanted to follow python zen `implicit is better then explicit` nice advise though – The6thSense Nov 03 '15 at 09:50
  • 1
    what about simple `dicts[key].get('score')` ? if the key is not in dict it will return `None` – BernarditoLuis Nov 03 '15 at 09:51
  • 1
    Well, see [this question](http://stackoverflow.com/questions/9494404/use-of-true-false-and-none-as-return-values-in-python-functions). And by the way, if you really would like be more implicit, you can use `if dicts[key].get('score', False) is not False:` instead(I think it's more implicit than `!=`. But I still recommend `if dicts[key].get('score', False):`(or just `if dicts[key].get('score'):`)). – Remi Guan Nov 03 '15 at 09:53
  • @KevinGuan yes changed – The6thSense Nov 03 '15 at 09:55
  • 1
    @KevinGuan shall i add your comment as an extra code to my answer – The6thSense Nov 03 '15 at 09:58
  • Okay if you'd like :) – Remi Guan Nov 03 '15 at 10:02
1

What about using OrderedDict?

from collections import OrderedDict

origin_dict = {
    1: {'age':1,'cost':14,'score':0.3}, 
    2: {'age':1,'cost':9,'score':0.5}, 
    3: {'age':1,'cost':8,'score':0.45}
}
# sort by score
sorted_dict = OrderedDict(sorted(origin_dict.items(), key=lambda x: x[1]['score']))
# now all you have to do is to count sum_cost successively starting from 0
sum_cost = 0
for key, value in sorted_dict.items():
    value['sum_cost'] = sum_cost
    sum_cost += value['cost']

print sorted_dict
Remi Guan
  • 21,506
  • 17
  • 64
  • 87
BernarditoLuis
  • 157
  • 3
  • 12