Jonathan Ludwig
Jonathan Ludwig

Reputation: 17

More questions 'simple' Grocery List

Yesterday I posted a question about a grocery list and recieved a lot of help with it. I have encountered another problem with it. Here is my code:

item = {}
while True:
    x = input('enter item: ')
    if x =='done':
         break
    y = float(input('enter price: '))

    item[x] = (y)

slist = {}
print('How much do you want of everything?')
while True:
    listitem = input("Item name: ")
    if listitem == 'done':
        break
    qty = float(input("How many: "))
    slist[listitem] = qty



total = 0
for key in item:
    value = item[key] * slist[key]
    total = total + value
print(total)   

The problem comes when you input an item for the first loop and then don't input it for the second one. For example, putting in: Milk, 5 - Eggs, 3 - Bread, 2, into the first loop and then only including Milk and Eggs for the second loop results in an error:

Traceback (most recent call last):
   File "V:\Downloads\grocery list.py", line 24, in <module>
     value = item[key] * slist[key]
KeyError: 'Bread'

What can I do to prevent this from happening?

Upvotes: 1

Views: 736

Answers (2)

timgeb
timgeb

Reputation: 78760

Instead of looping

for key in item

you should be doing

for key in slist

since item contains all items in the store and slist only the purchased items. slist is a bad name by the way, it's a dictionary, not a list.

Demo with adjusted code:

enter item: Milk
enter price: 5
enter item: Eggs
enter price: 3
enter item: Bread
enter price: 2
enter item: done
How much do you want of everything?
Item name: Milk
How many: 2
Item name: Eggs
How many: 1
Item name: done
13.0

Upvotes: 1

ShadowRanger
ShadowRanger

Reputation: 155516

Change:

value = item[key] * slist[key]

to:

value = item[key] * slist.get(key, 0)

dict.get is used when you want to get a value if it exists, or get a default value otherwise. That makes it so, if slist doesn't contain key (you didn't actually want that item), you treat it as having a count of 0 (if it does have the key, the default 0 is ignored).

Alternatively, flip your loop to loop over the shopping list (for key in slist:) rather than the inventory, and leave the calculation unchanged. In that case, you want the exception; if your shopping list contains an item that isn't in the store, you want the attempt to look up its price to fail.

Side-note: Not necessary for correctness, but if you're using both the key and the value, it's easier to iterate them both in parallel, rather than just iterating keys, and looking up the value later. It also lets you provide more useful names so the code self-documents. The loop could be changed to (for example):

for listitem, wanted in slist.items():
    value = item[listitem] * wanted 
    total += value

avoiding repeated lookup and making the intent more clear.

Upvotes: 1

Related Questions