tcokyasar
tcokyasar

Reputation: 592

Sum values of a Dictionary with "similar" keys Python

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

Answers (2)

atru
atru

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

chakradhar kasturi
chakradhar kasturi

Reputation: 699

  1. Generate the items from the dictionary
  2. Construct a list comprehension with tuple items by removing Cost. e.g., Cost1,(1,2) will be (1,2), and Cost2,(1,2) will also be (1,2)
  3. Sort the list so all key items will ordered
  4. Groupby using itertools and sum and store it in a dict
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

Related Questions