Reputation: 592
I have the following dictionary:
CostofA = {'Cost1,(1, 2)': 850.93,
'Cost1,(1, 2, 3)': 851.08,
'Cost1,(1, 3)': 851.00,
'Cost1,(1,)': 850.86,
'Cost2,(1, 2)': 812.56,
'Cost2,(1, 2, 3)': 812.65,
'Cost2,(2, 3)': 812.12,
'Cost2,(2,)': 812.04,
'Cost3,(1, 2, 3)': 717.93,
'Cost3,(1, 3)': 717.88,
'Cost3,(2, 3)': 717.32,
'Cost3,(3,)': 717.27}
From this dictionary, I want to create the following dictionary by adding up the elements that have similar keys. For example, I want to sum the values of 'Cost1,(1, 2, 3)'
, 'Cost2,(1, 2, 3)'
, and 'Cost3,(1, 2, 3)'
as they have the same numbers inside the parentheses (1, 2, 3)
and create 'Cost(1, 2, 3)': 2381.66
. Similarly, 'Cost1,(1, 3)'
and 'Cost3,(1, 3)'
have the same numbers inside the parentheses, so, I want to sum 851.00
and 717.88
and write it to my new dictionary as: 'Cost(1, 3)': 1568.88
. For 'Cost1,(1,)'
, 'Cost2,(2,)'
, and 'Cost3,(3,)'
, I do not want to do anything but to add them to the new dictionary. If I can get rid of the comma right after the 1 in the parentheses, it would be perfect. So, what I mean is: 'Cost1,(1,)': 850.86
becomes 'Cost(1)': 850.86
.
CostofA = {'Cost(1)': 850.86,
'Cost(2)': 812.04,
'Cost(3)': 717.27,
'Cost(1, 2)': 1663.58,
'Cost(1, 3)': 1568.88,
'Cost(2, 3)': 1529.34,
'Cost(1, 2, 3)': 2381.66}
I know I can reach to the keys of the dictionary by
CostofA.keys()
and I know I may create a logic with a for loop and an if condition to create the above dictionary, however, I cannot think of a way to reach the numbers in the parentheses inside this if statement. Any suggestions?
Upvotes: 2
Views: 2268
Reputation: 4744
This is one solution:
import re
str_pat = re.compile(r'\((.*)\)')
Cost = {}
for key, value in CostofA.items():
match = str_pat.findall(key)[0]
if match.endswith(','): match = match[:-1]
temp_key = 'Cost(' + match + ')'
if temp_key in Cost:
Cost[temp_key] += value
else:
Cost[temp_key] = value
CostofA = Cost
This creates a new dictionary Cost
with keys built based on the numbers enclosed by brackets in the original dictionary CostA. It uses a precompiled regex to match those numbers after which it checks with endswith(',')
if the matched pattern end with a ,
like in (1,)
- if it does, it removes it.
It then explicitly concatenates the pattern with brackets and other desired strings creating the target new key. If the new key exists, the program increases it's value by the value from the old dictionary. If it does not - it creates a new entry with that value. At the end, the program overwrites the old dictionary.
re.compile is a compiled regex object as said in the documentation:
Compile a regular expression pattern into a regular expression object, which can be used for matching using its match() and search() methods, described below.
It stores a given fixed regex pattern for searching and is considered to be more efficient than calling a new regex each time, especially when the program does more matching with that same pattern,
but using re.compile() and saving the resulting regular expression object for reuse is more efficient when the expression will be used several times in a single program.
Here it is used more for clarity as it defines the pattern once upfront rather then each time in the loop, but if your original dictionary was larger it could actually provide some performance improvements.
Upvotes: 1
Reputation: 699
from itertools import groupby data = sorted([(i[0].split(",",1)[1].replace(",)",")"),i[1]) for i in CostofA.items()]) for key, group in groupby(data, lambda x: x[0]): new_dict["Cost"+key] = sum([thing[1] for thing in group])
Upvotes: 2