merge values of same key in a list of dictionaries , and compare to another list of dictionaries in python3
Question: **Update:** Apparently, I noticed that in my main code, when I extract the
values from the list of dictionaries that I get from readExpenses.py, I store
it as a set, not as a list of dictionaries.

Now, I know that I store each dictionary in the 'exp' list with these lines of
code:

    
    
    for e in expenses:
    
        exp.append(e)
    

However, I only want the Keys Amount, and Type from those dictionaries, and
not the other entries.

For reference, here is the list of keys in an expense dictionary:

    
    
    "Date","Description","Type","Check Number","Amount","Balance"
    

As mentioned before, I only need Type and Amount.

I am trying to make a budget program, So I have this list of dictionaries:

    
    
    [{'Bills': 30.0}, {'Bills': 101.53}, {'Bills': 60.0}, {'Bills': 52.45}, {'Gas': 51.17}, {500.0: 'Mortgage'}, {'Food': 5.1}]
    

And I'm trying to compare it to this list of dictionaries:

    
    
    [{400.0: 'Bills'}, {'Gas': 100.0}, {500.0: 'Mortgage'}, {'Food': 45.0}]
    

The first list is how much money I spent on different services in a given
month, and what category it was in, and the second dictionary is the max
amount that the budget allows me to spend on said category.

The goal is, in the first dictionary, to combine all the values of the same
key into one key:value pair, then compare it to the second dictionary.

So I should get this list of dictionaries out of the first one:

    
    
    [{'Bills': 295.15), {'Gas': 51.17}, {500.0: 'Mortgage'}, {'Food': 5.1}]
    

I tried looking at [this
example](http://stackoverflow.com/questions/3421906/how-to-merge-lists-of-
dictionaries "this example") and [this
one](http://stackoverflow.com/questions/38987/how-can-i-merge-union-two-
python-dictionaries-in-a-single-expression), but they are just about merging
the dictionaries lists together, and not summing the values of the same key. I
did try the code in the latter, but it only joined the dictionaries together.
I noticed that sum only seems to work with "raw" dictionaries, and not with
lists of dictionaries.

I did try this as a thought experiment:

    
    
    print(sum(item['amount'] for item in exp))
    

I know that would sum up all the numbers under amount, rather than return a
number for each category, but I wanted to try out it for the heck of it, to
see if it would lead to a solution, but I got this error in return:

    
    
    TypeError: 'set' object is not subscriptable
    

The Counter function seemed to show promise as a solution as well when I was
messing around, however, it seems to only work with dictionaries that are on
their own, and not with list of dictionaries.

    
    
    #where exp is the first dictionary that I mentioned
    a = Counter(exp)
    b = Counter(exp) 
    
    c = a + b #I'm aware the math would have be faulty on this, but this was a test run
    print (c)
    

This attempt returned this error:

    
    
    TypeError: unhashable type: 'set'
    

Also, is there a way to do it without importing the collections module and
using what comes with python as well?

My code:

    
    
    from readExpense import *
    from budget import *
    from collections import *
    
    #Returns the expenses by expenses type
    def expensesByType(expenses, budget):
    
        exp = []
    
        expByType = []
    
        bud = []
    
    
        for e in expenses:
    
            entry = {e['exptype'], e['amount']}
    
            exp.append(entry)
    
        for b in budget:
            entry = {b['exptype'], b['maxamnt']}
    
            bud.append(entry)
    
    
    
        return expByType;
    
    
    def Main():
    
        budget = readBudget("budget.txt")
        #printBudget(budget)
    
        expenses = readExpenses("expenses.txt")
        #printExpenses(expenses)
    
        expByType = expensesByType(expenses, budget)        
    
    if __name__ == '__main__':
        Main()
    

And for reference, the code from budget and readexpense respectively.

budget.py

    
    
    def readBudget(budgetFile):
        # Read the file into list lines
        f = open(budgetFile)
        lines = f.readlines()
        f.close()
    
        budget = []
    
        # Parse the lines
        for i in range(len(lines)):
            list = lines[i].split(",")
    
            exptype = list[0].strip('" \n')
            if exptype == "Type":
                continue
    
            maxamount = list[1].strip('$" \n\r')
    
            entry = {'exptype':exptype, 'maxamnt':float(maxamount)}
    
            budget.append(entry)
    
        return budget
    
    def printBudget(budget):
        print()
        print("================= BUDGET ==================")
        print("Type".ljust(12), "Max Amount".ljust(12))
    
        total = 0
        for b in budget:
            print(b['exptype'].ljust(12), str("$%0.2f" %b['maxamnt']).ljust(50))
            total = total + b['maxamnt']
    
        print("Total: ", "$%0.2f" % total)
    
    def Main():
        budget = readBudget("budget.txt")
        printBudget(budget)
    
    if __name__ == '__main__':    
        Main()
    

readExpense.py

    
    
    def readExpenses(file):
    
        #read file into list of lines
        #split lines into fields
        # for each list create a dictionary
        # add dictionary to expense list
    
        #return expenses in a list of dictionary with fields
        # date desc, exptype checknm, amnt
    
        f = open(file)
        lines=f.readlines()
        f.close()
    
        expenses = []
    
        for i in range(len(lines)):
            list = lines[i].split(",")
    
            date = list[0].strip('" \n')
            if date == "Date":
                continue
    
            description = list[1].strip('" \n\r')
            exptype= list[2].strip('" \n\r')
            checkNum = list[3].strip('" \n\r')
            amount = list[4].strip('($)" \n\r')
            balance = list[5].strip('" \n\r')
    
            entry  ={'date':date, 'description': description, 'exptype':exptype, 'checkNum':checkNum, 'amount':float(amount), 'balance': balance}
    
            expenses.append(entry)
    
        return expenses
    
    def printExpenses(expenses):
    
        #print expenses
        print()
        print("================= Expenses ==================")
        print("Date".ljust(12), "Description".ljust(12), "Type".ljust(12),"Check Number".ljust(12), "Amount".ljust(12), "Balance".ljust(12))
    
        total = 0
    
        for e in expenses:
            print(str(e['date']).ljust(12), str(e['description']).ljust(12), str(e['exptype']).ljust(12), str(e['checkNum']).ljust(12), str(e['amount']).ljust(12))
            total = total + e['amount']
    
    
        print()
    
        print("Total: ", "$%0.2f" % total)
    
    def Main():
        expenses = readExpenses("expenses.txt")
        printExpenses(expenses)
    
    if __name__ == '__main__':
        Main()
    


Answer: Is there a reason you're avoiding creating some objects to manage this? If it
were me, I'd go objects and do something like the following (this is
completely untested, there may be typos):

    
    
    #!/usr/bin/env python3
    
    from datetime import datetime # why python guys, do you make me write code like this??
    from operator import itemgetter
    
    class BudgetCategory(object):
        def __init__(self, name, allowance):
            super().__init__()
                self.name = name # string naming this category, e.g. 'Food'
                self.allowance = allowance # e.g. 400.00 this month for Food
                self.expenditures = [] # initially empty list of expenditures you've made
    
        def spend(self, amount, when=None, description=None):
            ''' Use this to add expenditures to your budget category'''
            timeOfExpenditure = datetime.utcnow() if when is None else when #optional argument for time of expenditure
            record = (amount, timeOfExpenditure, '' if description is None else description) # a named tuple would be better here...
            self.expenditures.append(record) # add to list of expenditures
            self.expenditures.sort(key=itemgetter(1)) # keep them sorted by date for the fun of it
    
        # Very tempting to the turn both of the following into @property decorated functions, but let's swallow only so much today, huh?
        def totalSpent(self):
            return sum(t[0] for t in self.expenditures)
    
        def balance(self):
            return self.allowance - self.totalSpent()
    

Now I can right code that looks like:

    
    
    budget = BudgetCategory(name='Food', allowance=200)
    budget.spend(5)
    budget.spend(8)
    
    print('total spent:', budget.totalSpent())
    print('left to go:', budget.balance())
    

This is just a starting point. Now you can you add methods that group (and
sum) the expenditures list by decoration (e.g. "I spent HOW MUCH on Twinkies
last month???"). You can add a method that parses entries from a file, or
emits them to a csv list. You can do some charting based on time.

