0

I have an assignment to take in user input to create a grocery list of items, and to eventually output this information along with a grand total onto a receipt.

Example: The user inputs the following grocery items:
{'name':'milk', 'number': 1, 'price': 2.00}, {'name':'eggs', 'number':2, 'price': 3.99}, {'name': 'onions', 'number': 4, 'price':0.79}.

Then I would want my ouput to be:

1 milk @ $2.99 ea $2.99
2 eggs @ $3.99 ea $7.98
4 onions @ $0.79 ea $3.16
Grand total: $14.13

Instead my ouput is:

4 onions @ $0.79 ea $3.16
4 onions @ $0.79 ea $3.16
4 onions @ $0.79 ea $3.16
Grand total: $9.48

Here is the code I am using. I have a strong feeling my for loop is to blame (they have been the hardest thing to master for me), but I'm not sure why it is only printing the last entry over and over.

grocery_item = {}

grocery_history = []

stop = 'go'

while stop != 'q' :
    item_name = input("Item name:\n")
    quantity = input("Quantity purchased:\n")
    cost = input("Price per item:\n")

    grocery_item['name'] = item_name
    grocery_item['number'] = int(quantity)
    grocery_item['price'] = float(cost)

    grocery_history.append(grocery_item)

print("Would you like to enter another item?")
stop = input("Type 'c' for continue or 'q' to quit:\n")

grand_total = []

for grocery_item in grocery_history:

    item_total = grocery_item['number'] * grocery_item['price']
    grand_total.append(item_total)
    print(grocery_item['number'], end=' ')
    print(grocery_item['name'],end=' ')
    print('@', end=' ')
    print('$%.2f' % (grocery_item['price']), end=' ')
    print('ea', end=' ')
    print('$%.2f' % (item_total))
    item_total = 0

sum = sum(grand_total)
print('Grand total: $%.2f' % (sum))
martineau
  • 119,623
  • 25
  • 170
  • 301
OmarXShay
  • 13
  • 4
  • post the code on how are you populating `grocery_history` – Pankaj Singhal Dec 24 '17 at 17:03
  • Did you by any chance do `[{}] * 3`? – cs95 Dec 24 '17 at 17:03
  • 1
    Here we go. Move `grocery_item = {}` into the loop, or else you append the _same_ dictionary to the list _each time_. So, if you modify one, you modify them all _just the same_. – cs95 Dec 24 '17 at 17:17
  • I apologize again - just included all of my previous code as well! – OmarXShay Dec 24 '17 at 17:18
  • @cᴏʟᴅsᴘᴇᴇᴅ thank you so much! It's always the (seemingly) simplest things!! – OmarXShay Dec 24 '17 at 17:24
  • i think you'd be better off going with a list of namedtuples, as your keys are redundant across all dictionaries. see [here](https://stackoverflow.com/questions/9872255/when-and-why-should-i-use-a-namedtuple-instead-of-a-dictionary) – 0TTT0 Dec 24 '17 at 18:10

4 Answers4

0

You can use string formatting:

s = [{'name':'milk', 'number': 1, 'price': 2.00}, {'name':'eggs', 'number':2, 'price': 3.99}, {'name': 'onions', 'number': 4, 'price':0.79}]
for val in s:
   print("{number} {name} @ ${price} ea ${final}".format(**{**val, **{'final':val['number']*val['price']}}))
print('Grand Total: $'+str(sum(val['price']*val['number'] for val in s)))

Output:

1 milk @ $2.0 ea $2.0
2 eggs @ $3.99 ea $7.98
4 onions @ $0.79 ea $3.16
Grand Total: $13.14

Edit: regarding your code you added for grocery_item initialization, grocery_item is always being updated at each iteration. Instead, declare grocery_item in the scope of the while loop:

while stop != 'q':
   grocery_item = {}
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
  • @cᴏʟᴅsᴘᴇᴇᴅ in that case we must wait until the OP clarifies what the contents of `grocery_history` are. – Ajax1234 Dec 24 '17 at 17:11
  • Exactly! Ideally, one would first ask for this clarification and _then_ write the answer. ;-) I have my doubts that your answer as it stands is going to help OP (hint: see my comment) – cs95 Dec 24 '17 at 17:12
  • @COLDSPEED I'm sorry about that! Fixing that now to include all of my code. I was trying to keep it as brief as possible. – OmarXShay Dec 24 '17 at 17:14
0

Your Code is working fine ,I tested it in my PC. Check this code

grocery_history = [{'name':'milk', 'number': 1, 'price': 2.00}, {'name':'eggs', 'number':2, 'price': 3.99}, {'name': 'onions', 'number': 4, 'price':0.79}]
grand_total = []

for grocery_item in grocery_history:

    item_total = grocery_item['number'] * grocery_item['price']
    grand_total.append(item_total)
    print(grocery_item['number'], end=' ')
    print(grocery_item['name'],end=' ')
    print('@', end=' ')
    print('$%.2f' % (grocery_item['price']), end=' ')
    print('ea', end=' ')
    print('$%.2f' % (item_total))
    item_total = 0

sum = sum(grand_total)
print('Grand total: $%.2f' % (sum))

Here is the result:

"C:\Programs\Python\Python35\python.exe" F:/MyJobs/StackOverflow/StackOverflow.py
1 milk @ $2.00 ea $2.00
2 eggs @ $3.99 ea $7.98
4 onions @ $0.79 ea $3.16
Grand total: $13.14

Process finished with exit code 0

You should check the way , how "grocery_history" is assigned.

  • If it works for you, and if the only thing you did differently from the question is the way you initialised you `grocery_history`, then it follows that the issue lies with the initialisation of that data structure. Writing an answer proclaiming that OP's code works, rather than getting to the root cause, isn't helping OP. – cs95 Dec 24 '17 at 17:14
0

I got this code hope it helps: [Python3.6]

items = [{'name':'milk', 'number': 1, 'price': 2.00}, {'name':'eggs', 'number':2, 'price': 3.99}, {'name': 'onions', 'number': 4, 'price':0.79}]
grand_total = 0.0
for item in items:
    item_total = item['price'] * item['number']
    grand_total += item_total
    print('{number} {name} @ ${price} ea $'.format(**item) + '{0}'.format(item_total))
print('Grand total: ${0}'.format(grand_total))
Gabriel
  • 76
  • 5
  • No, in all probability does not help. The issue is 99% the manner in which OP has created their data. I don't know what you're doing here, but I don't think it'll do anything different for OP. – cs95 Dec 24 '17 at 17:15
0

Your grocery_history has 3 elements, for which all 3 of them are all referring to same grocery_item

You keep reusing the same instance of dict as grocery_item, and put the same instance into the grocery_history multiple times.

A quick fix is

while stop != 'q' :
    item_name = input("Item name:\n")
    quantity = input("Quantity purchased:\n")
    cost = input("Price per item:\n")

    grocery_item = {}   # a new dict
    grocery_item['name'] = item_name
    grocery_item['number'] = int(quantity)
    grocery_item['price'] = float(cost)
    # or simply do 
    # grocery_item = { "name" : item_name, "number": int(quantity)... }

    grocery_history.append(grocery_item)
Adrian Shum
  • 38,812
  • 10
  • 83
  • 131