0

I was trying to solve a homework question that involves processing an order based on a list of tuples which contain the name of item, quantity, and price per item.

The total is calculated by taking the 1st and 2nd indices of each tuple in the list after the item is removed and then summing the products for each tuple in the list remaining.

I have to do these things within the process_order() function, but I keep on running into issues when I'm trying to remove one tuple from the list because the while loop keeps running and deletes all the elements always making the total equal to 0.

The starting code is like this:

total = 0 

def process_order(x_list):

x = [("oranges", 4, 3.22),("gummy bears",1,1.99),("sour bites", 3, 2.33), ("antacid", 1, 5.33)]
while(len(x)>0):
  process_order(x)
print("total price: ", total)
pythonRCNewbie
  • 309
  • 1
  • 2
  • 6

2 Answers2

0

Here it is,

total = 0
x = [("oranges", 4, 3.22),
     ("gummy bears", 1, 1.99),
     ("sour bites", 3, 2.33),
     ("antacid", 1, 5.33)]

def process_order(x_list):
    # calculate the cost of the first element and remove it
    cost = x_list[0][1] * x_list[0][2]
    del x_list[0]
    return cost

while x:
    total += process_order(x)

print(total)
# 27.19
BcK
  • 2,548
  • 1
  • 13
  • 27
  • Hi BcK, this is an interesting approach. How would I go about doing reverse deletion if I wanted to remove any random index within the length of the list? – pythonRCNewbie Jun 28 '18 at 06:14
  • I realized that there is no need to delete from the end. You can delete from anywhere in the list. Just give a random index within the range of the list. – BcK Jun 28 '18 at 06:16
  • Also, I'm not allowed to change any of the code below the process_order() function. – pythonRCNewbie Jun 28 '18 at 06:16
0

I decided to add a second answer in response to this comment under BcK's answer:

Also, I'm not allowed to change any of the code below the process_order() function.

This... is technically doable, but the question is subsequently kind of strange to me. In order for the code below the definition of process_order to work without modification, you have to make a change to how you define total. I find this strange because changing total is only permissible due to the fact that it's "technically above the definition of process_order" which seems like a pretty weak excuse to me.

The crux of the problem with total is the intuitive answer would be:

def process_order(x_list):
    {do stuff}
    total += quantity * cost

The reason this solution doesn't work is because assigning a variable within a scope (in this example, the total = segment of total +=) creates a reference that supersedes the reference of any "higher" scopes. This means that total either cannot be assigned within the scope of process_order (technically achievable given the current restrictions, but requiring a bit of hackery), or a reference to the total variable that exists in the outer scope needs to make its way into the inner scope.

The simplest way to achieve the latter is to use the global keyword. I really, really don't like the global keyword (and there are people who agree with me), but for whatever reason it keeps popping up, so here's how you would use it (as well as an alternative way of writing process_order for your learning pleasure).

## Declare total as global variable
global total
## Set total
total = 0

def process_order(x_list):
    """ Remove an an order item (as a tuple (name, quantity, cost) ) from x_list and add it to the global total"""

    ## Let the interpreter know that you plan on using total in this scope
    global total

    ## List.pop is a good way to incrementally destroy a list
    ## (you can use an index as an argument: the default is -1)
    item = x_list.pop()

    ## This takes advantage of sequence unpacking and multiple assignment
    (name,quantity,price) = item

    ## You can now assign to total because it has been declared as a global variable
    total += quantity * price


## The rest is unchanged
x = [("oranges", 4, 3.22),("gummy bears",1,1.99),("sour bites", 3, 2.33), ("antacid", 1, 5.33)]
while(len(x)>0):
  process_order(x)
print("total price: ", total)
## Outputs: >> total price:  27.19

All that being said, I would sooner assume that there was some miscommunication in the assignmet; changing the while loop to match BcK's example would make significantly more sense, in my opinion.

Reid Ballard
  • 1,480
  • 14
  • 19