简体   繁体   中英

Python - List nested in dict - how to sum single value

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'

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

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

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM