0

I tried reading through many similar questions (this seemed closest: Python sum dict values based on keys) but still struggling to answer the following question below. Boiling it down to basics

I have the following 3 dictionaries with lists as keys:

{'milk': ['gallons', 5, 10, 50]}
{'eggs': ['cartons', 5, 2, 10]}
{'bacon': ['packages', 5, 7, 35]}

I want to be able to sum the last value of each nested list and have an expected, single value of 95 printed to the screen.

I've seen answers to similar questions that involve lambdas but I know there has to be a way to do this with iterating through the list. I've seen the use of sum and Counter and am open to any explanations. Thank you in advance.

UPDATE/ADDED CONTEXT

Thank you to those who have already been responding. I realize more context may be needed to answer this.

These entries are being made from this class:

class GroceryCart(dict):

    def __init__(self):
        self = {}

    def addToCart(self, item, units, quantity, price):
        item_total = quantity*price
        self.update({item:[units, quantity, price, item_total]})

    def returnCart(self):
        return self

my_cart = GroceryCart()

That is where you are getting the funky structure of info. I tried @ggorlan's response below but got traceback errors about not having str values to use .values()

Traceback (most recent call last):
  File "grocery_store.py", line 156, in <module>
    total = sum(sum(y[-1] for y in x.values()) for x in my_cart)
  File "grocery_store.py", line 156, in <genexpr>
    total = sum(sum(y[-1] for y in x.values()) for x in my_cart)
AttributeError: 'str' object has no attribute 'values'
PolishZeus
  • 13
  • 4
  • Lists can't be keys in a dictionary. Lists can only be values (as you have in your example). Also, are these three dictionaries in a larger data structure? – Noufal Ibrahim Apr 16 '18 at 04:32
  • What have you tried so far? – Klaus D. Apr 16 '18 at 04:32
  • 1
    if your dictionary is a then sum([a[k][3] for k in a]) will print 95, but you have to write a as {'bacon': ['packages', 5, 7, 35], 'eggs': ['cartons', 5, 2, 10], 'milk': ['gallons', 5, 10, 50]} – Osman Mamun Apr 16 '18 at 04:35
  • I've tried adapting things like [this list comprehension and loop example](http://blog.rizauddin.com/2009/05/how-to-sum-values-of-python-dictionary_7174.html) and from [this post](https://stackoverflow.com/questions/11692613/python-sum-values-in-dictionary) trying to experiment with the solution to see if it can be applied to my scenario. Tbh it's been a lot of flailing and trying to systematically drill down to find out how to call the last value of the list. But if I can do that, would I store it in a new list to sum after iterating through? – PolishZeus Apr 16 '18 at 04:40
  • I think you need to step back and tell us what you're trying to do in a broader way. This looks like a wrong way to manage your data. – Noufal Ibrahim Apr 16 '18 at 04:50
  • @NoufalIbrahim Just added more context. You are right--this has a lot to do with me being new to python. Hence the weird data management. – PolishZeus Apr 16 '18 at 04:55
  • Are you sure you want to subclass from `dict`? I'd create an internal variable that's a dict which stores the data. Something like `self.items = {}` rather than subclass from `dict`. – Noufal Ibrahim Apr 16 '18 at 05:12
  • Also, assigning to `self` doesn't make sense here. – Noufal Ibrahim Apr 16 '18 at 05:12

4 Answers4

2

This is a strange structure. It looks like your values are lists, not the keys. If I assume the three objects are in an array, here's an attempt:

food = [
    {'milk': ['gallons', 5, 10, 50]},
    {'eggs': ['cartons', 5, 2, 10]},
    {'bacon': ['packages', 5, 7, 35]}
]

total = sum(list(x.values())[0][-1] for x in food)
print(total) # 95
ggorlen
  • 44,755
  • 7
  • 76
  • 106
1

Assuming you want your dictionaries in a list, use the following code. Two for loops are required: the first iterates through foods which is a list of dictionaries and the second iterates through the values in the dictionary that's currently being iterated over. food.values() yields the lists in your dictionary and lst[-1] selects the last element from the list that's currently being iterated over.

foods = [
    {'milk': ['gallons', 5, 10, 50]},
    {'eggs': ['cartons', 5, 2, 10]},
    {'bacon': ['packages', 5, 7, 35]}
]

sum = 0
for food in foods:
    for details in food.values():
        sum += details[-1]
print(sum)  # 95

Otherwise assuming you want them as one dictionary, use the following code. This time only one for loop is needed to iterate through the dictionary's every value.

foods = {
    'milk': ['gallons', 5, 10, 50],
    'eggs': ['cartons', 5, 2, 10],
    'bacon': ['packages', 5, 7, 35]
}

sum = 0
for lst in foods.values():
    sum += lst[-1]
print(sum)  # 95
chambln
  • 363
  • 1
  • 2
  • 9
  • The second options gets me verrrrry close to what I'm after. Though the output is: 50 60 95 ||| So I'm assuming there is a small modification to only show the final sum? – PolishZeus Apr 16 '18 at 05:11
0

I assume, given the nature of your question that it's probably for a class assignment, in which case I would seriously consider asking your teacher/professor if they want single-key dictionaries, because it seems a lot more likely that they would want that rather than the data structure you have devised. That being said, @contrum has a lovely solution for solving it as a multi-key dictionary; Otherwise, since you've stated that you want to iterate the dictionaries and it's pretty easy to append lists, the following should work just fine for you while also having a puntastic name:

def getSum(dictList):
    result = 0
    dictList = [{'milk': ['gallons', 5, 10, 50]}, {'eggs': ['cartons', 5, 2, 10]}, {'bacon': ['packages', 5, 7, 35]}]
    for richard in dictList:
        for key in richard:
            result += richard[key][len(richard[key]) - 1]
    return result
democidist
  • 105
  • 1
  • 6
0

Try this:

foods = {
    'milk': ['gallons', 5, 10, 50],
    'eggs': ['cartons', 5, 2, 10],
    'bacon': ['packages', 5, 7, 35]
}

s = sum([item[-1] for item in foods.values()])

The s will be 95.

Mehrdad Pedramfar
  • 10,941
  • 4
  • 38
  • 59