Hey guys,

I'm trying to create a buy and sell program where I have two lists of numbers. Eventually I want to shorten the lists so that the program buys at a lower number, and sells at a higher number, ignoring all other numbers in between.

The solution would be

SellList = [7,10,12]

I'm having problems with the range in my for loops.

``````BuyList = [1,2,3,4,9,11]
SellList = [0,7,8,10,12,15]

length_of_sell_list = []
myrange = 0

length_of_sell_list = len(SellList)

myrange = length_of_sell_list
else:
myrange = length_of_buy_list #if they are the same length, just pick one.

for x in range(0,myrange-1): #end of range is smaller list so it doesnt go out of range. keep deleting items until everything is in the same range.

myrange = length_of_sell_list
else:
myrange = length_of_buy_list #if they are the same length, just pick one.

for x in range(0,myrange-1): #end of range is smaller list so it doesnt go out of range. keep deleting items until everything is in the same range.
if (SellList[x] - BuyList[x]) < 0:
del SellList[x] #This takes the zero out of my SellList. Delete at the end of the loop otherwise stuff before it will mess up range.

myrange = length_of_sell_list
else:
myrange = length_of_buy_list #if they are the same length, just pick one.

print SellList

Here is a common error I get:

Traceback (most recent call last):
IndexError: list index out of range

I tried to address it by constantly changing the myrange integer to always be appropriate for the length of the smallest list. Any other ideas?

## All 12 Replies

I'm curious why you have the lines

``````length_of_buy_list = []
length_of_sell_list = []
...
length_of_sell_list = len(SellList)``````

You declared them as empty lists, then changed them to an integer of the list length...

And also, you store these lengths at the beginning but you don't change them throughout the script even though you have things like `del BuyList[x]` which will subtract from that list's length. Just don't use these variables you made and use `len(SellList)` and `len(BuyList)` everywhere else instead. That'll make sure that the real length of the lists is counted.

Do that and it may fix your range error. Tell me what result you get from that.

EDIT:
You can also change your conditionals from

``````if length_of_buy_list < length_of_sell_list:
myrange = length_of_sell_list
else:

to

``````if length_of_buy_list > length_of_sell_list:
myrange = length_of_sell_list
else:

because that sets "myrange" to the length of the buy list if its length is less than or equal to the sell list's length. Just a cleaner looking way of writing it.

Not quite sure what you want, but maybe function zip() will help:

``````buy_list = [1,2,3,4,9,11,77,99]
sell_list = [0,7,8,10,12,15]

# removes the excess items of the longer list

"""
my display -->
[(1, 0), (2, 7), (3, 8), (4, 10), (9, 12), (11, 15)]
1 0
2 7
3 8
4 10
9 12
11 15

"""``````

Thanks shadwickman. I made some changes and I'm still getting the same error. Here is a simpler version of it.

``````BuyList = [1,2,3,4,9,11]
SellList = [0,7,8,10,12,15]

myrange = 0

else:
myrange = len(SellList)

for x in range(0,myrange-1):

else:
myrange = len(SellList)``````

Traceback (most recent call last):
IndexError: list index out of range

The problem only arises when I delete an item from the BuyList or SellList. I know this changes the range but I thought I had accounted for that by changing the range at every point. Any ideas?

Actually, I hadn't realized it before but no matter what, your range will go to the pre-set length, yet you're removing items from the list, which is shortening it to less than that pre-set range. Changing the range inside the for loop has no effect either.
This will allow you to adjust the range inside the loop:

``````BuyList = [1,2,3,4,9,11]
SellList = [0,7,8,10,12,15]

myrange = 0

else:
myrange = len(SellList)

x = 0
while x < myrange:
myrange -= 1
x += 1

print SellList

"""
Output:
[1, 3, 9, 11]
[0, 7, 8, 10, 12, 15]
"""``````

I'm still not 100% sure what you're trying to achieve with this code... unless you want it to assign the biggest "sell" index possible to each "buy" index? So there is the biggest difference between indices of the two lists?

Anyways, you should look at Ene Uran's code because that may be what you're looking for, as it looks close to what you want and it's a nice, clean-looking solution.

Thanks Ene. But I'm trying to get the low numbers in the buy list and attach it to the first available number greater than that low number in the sell list.

So the program should:

Sell at period 7

Sell at period 10

Sell at period 12

The condition is that you can only hold one buy at a time. Until you sell it, you cannot hold another buy. And you want to buy on the first available date you can buy, which is the first available item in the list.

Thanks Ene. But I'm trying to get the low numbers in the buy list and attach it to the first available number greater than that low number in the sell list.

So then why isn't this the solution:
1:7, 2:8, 3:10, 4:12, 9:15

That takes the low numbers in the buy list and attaches them to higher numbers in the sell list.

In your solution, you only listed 1:7, 9:10, 11:12. What happened to the "low numbers" of the buy list, as in 2, 3, and 4?

I'm trying to continue the looped function so that the 3 in the BuyList is deleted as well. Since 7 is > 3, 3 should be deleted too.

I need to create another delete function to delete items in the sell list.

my goal is to reduce the list to

[7,10,12] for the SellList

Your code is a good start. Maybe i'll nest the while loop in a for loop"?

So you want to remove any buy numbers that are below any of the sell numbers?

So then why isn't this the solution:
1:7, 2:8, 3:10, 4:12, 9:15

That takes the low numbers in the buy list and attaches them to higher numbers in the sell list.

In your solution, you only listed 1:7, 9:10, 11:12. What happened to the "low numbers" of the buy list, as in 2, 3, and 4?

The numbers in the lists are supposed to correspond to time period. Think of them as dates.

2,3,4 should be deleted in the Buy List

Because you use your buy ticket only one at a time. So you buy 1. Since 0 is a sell signal before period 1, you cannot go back in time to sell it, so delete 0.

Ok, that makes more sense once you said that they correspond to time periods. Before I just couldn't see a logical pattern to what you were matching up.

This code works, but it's kinda messy and hacked together. Not the best option but you can modify it from here. BuyResult and SellResult are the resulting lists with the correct output.

``````BuyList = [1,2,3,4,9,11]
SellList = [0,7,8,10,12,15]

# if SellResult don't contain something to start,
# then the 'SellResult[-1] < bn' will throw an error.
SellResult = [0]

if SellResult[-1] < bn:
for sn in SellList:
if sn > bn:
SellResult.append(sn)
break
# remove that starting 0 from SellResult
SellResult = SellResult[1:]

"""
My result:
1:7, 9:10, 11:12
"""``````

Tell me if you need clarification for the code.

Thanks! That's exactly what I was looking for. I was thinking of moving it into separate lists as well but worried that it would be an extra step.

I'm still not entirely sure why sell result cannot start as an empty list. And why we add and then delete a zero. I'll play with it and figure it out. Thanks.

I'm still not entirely sure why sell result cannot start as an empty list. And why we add and then delete a zero. I'll play with it and figure it out. Thanks.

I have the line `if SellResult[-1] < bn` inside the BuyList for loop, because that way it will only cycle through the SellList to compare the current buy value IF the current buy value is more than the previous sell value (SellResult[-1] = last number in SellResult).
If SellResult starts as an empty list, then calling the last index of it will result in an error of "list index out of range". All I did was start it off with a zero so that this if statement wouldn't cause errors with the SellResult right off the bat, then I just removed that zero at the end.
You can write it so that you don't need to start SellResult off with a value in it, but I did just so the code would look simpler.

Here's that other way with SellResult starting off blank:

``````BuyList = [1,2,3,4,9,11]
SellList = [0,7,8,10,12,15]

SellResult = []

def cycleSellList(bn):
for sn in SellList:
if sn > bn:
SellResult.append(sn)
break

if SellResult:  # if it contains values
if SellResult[-1] < bn:  # last number in it < bn
cycleSellList(bn)
else:  # no values in SellResult yet.
cycleSellList(bn)
"""
My result:
1:7, 9:10, 11:12
"""``````

Or if you don't want to use global variables:

``````BuyList = [1,2,3,4,9,11]
SellList = [0,7,8,10,12,15]

SellResult = []

def cycleSellList(bn):
for sn in SellList:
if sn > bn:
return sn

sn = None  # originally, no matching sell number

if SellResult:  # if it contains values
if SellResult[-1] < bn:  # last number in it < bn
sn = cycleSellList(bn)
else:  # no values in SellResult yet.
sn = cycleSellList(bn)

if sn != None:  # if it is something other than None