Reputation: 1581
I am trying to add the values of a dictionary of the same key(s). In my example below, I strip off the version numbering for each keys while trying to add the values of the 'same' key.
item_dict = {
"item_C_v001" : 100,
"item_C_v002" : 100,
"item_A_v001" : 50,
"item_B_v001" : 75
}
My expected output should be:
"item_C_v" : 200,
"item_A_v" : 50,
"item_B_v" : 75
but instead I got the following if I tried printing item_dict
:
"item_C_v" : 100,
"item_A_v" : 50,
"item_B_v" : 75
But the moment I tried to strip off, it seems that item_C_v
is read once. How can I make it read 'twice' so that I can get 200
as the output for it?
Upvotes: 0
Views: 83
Reputation: 30288
You can use itertools.groupby()
to collect all the similar keys and then construct a new dictionary summing up all the group values, e.g.:
>>> import itertools as it
>>> {gk: sum(item_dict[k] for k in g) for gk, g in it.groupby(item_dict, lambda k: k[:-3])}
{'item_A_v': 50, 'item_B_v': 75, 'item_C_v': 200}
@alecxe describes several methods to getting the desired part of the key, above uses key[-3]
.
There was a request to get both the count
and sum
, which you could implement in a simple loop and manage a counter but here's one way of doing it:
>>> from collections import deque
>>> {key: deque(enumerate(it.accumulate(item_dict[k] for k in g), 1), maxlen=1).pop()
... for key, g in it.groupby(item_dict, lambda key: key[:-3])}
{'item_A_v': (1, 50), 'item_B_v': (1, 75), 'item_C_v': (2, 200)}
Upvotes: 2
Reputation: 10671
You could iterate the original dictionary and append to the new dictionary the new keys, if the key already exists, add the current value to the original value.
item_dict = {
"item_C_v001" : 100,
"item_C_v002" : 100,
"item_A_v001" : 50,
"item_B_v001" : 75
}
new_dict = {}
for k, v in item_dict.items():
k_new = k[:-3]
new_dict[k_new] = new_dict[k_new] + v if k_new in new_dict.keys() else v
print (new_dict)
>>> {'item_A_v': 50, 'item_C_v': 200, 'item_B_v': 75}
Upvotes: 2
Reputation: 474131
You can use a collections.defaultdict(int)
to group and sum the result by a desired part of a key which you can get with, for example, a regular expression. Something along these lines:
In [1]: from collections import defaultdict
In [2]: import re
In [3]: item_dict = {
...: "item_C_v001" : 100,
...: "item_C_v002" : 100,
...: "item_A_v001" : 50,
...: "item_B_v001" : 75
...: }
In [4]: result = defaultdict(int)
In [5]: for key, value in item_dict.items():
...: result[re.search(r"(\w+?)\d+", key).group(1)] += value
In [6]: dict(result)
Out[6]: {'item_A_v': 50, 'item_B_v': 75, 'item_C_v': 200}
You can approach extracting the desired part of a key differently - with the str.partition()
:
>>> key = "item_C_v001"
>>> "".join(key.partition("_v")[:-1])
'item_C_v'
Or, simply via slicing, if the length of the substring before the digits or the number of digits at the end of the string is constant:
>>> key = "item_C_v001"
>>> key[:8]
'item_C_v'
>>> key[:-3]
'item_C_v'
Or, by right-stripping the digits:
>>> import string
>>> key.rstrip(string.digits)
'item_C_v'
Upvotes: 2