# Subsetting python list into positive/negative movements/trends

Sorry for creating this question but I have been stuck on this question for a while.

Basically I'm trying to take a list:

``numbers=[1, 2, -1, -2, 4, 5]``

And subset this list into a list of list that display positive/negative movements (or trends)

The end result is to have:

``subset_list = [[1, 2], [-1, -2], [4, 5]]``

Basically I have been using nested while functions to append a positive movement to the subset, and when the condition is not met, the subset is appended to subset_list and then evaluates if there is a negative movement.

I keep getting an `IndexError`, and so far `subset_list` only contains `[[1, 2]]`

Here is my code:

``numbers = [1,2,-1,-2,4,5]subset = []subset_list = []subset.append(numbers)i = 1while i < (len(numbers)):if numbers[i] <= numbers[i+1]:subset.append(numbers[i])i+= 1while subset[-1] <= numbers[i] or numbers[i] <= numbers[i+1]:subset.append(numbers[i])i += 1subset_list.append(subset)subset = []i += 1if numbers[i] > numbers[i+1]:subset.append(numbers[i])i+= 1while subset[-1] <= numbers[i] or numbers[i] <= numbers[i+1]:subset.append(numbers[i])i+= 1subset_list.append(subset)subset = []i += 1``

Thanks!

-Jake

This is what I came up with. It is close to what you have but a little easier to read. I avoid having to increment the index counter `i` as much which is probably where you went wrong.

``````n= [1,2,-1,-2,4,5]
out=[]
i=1
tmp=[n]
while i < len(n):
if n[i] >= 0 and tmp[-1] >= 0:
tmp.append(n[i])
elif n[i] < 0 and tmp[-1] < 0:
tmp.append(n[i])
else:
out.append(tmp)
tmp = [n[i]]
i = i + 1
if len(tmp) > 0: # typo fix was > 1
out.append(tmp)

print(out)
``````

Here is a way to re-write this:

``````
numbers=[1,2,-1,-2,4,5]

direction = True  # positive or negative
prevdirection = True
res = [[numbers]]

for previtem, item in zip(numbers[:-1], numbers[1:]):
direction = True if item - previtem > 0 else False
if direction != prevdirection:
res.append([])
prevdirection = direction
res[-1].append(item)

print(res)

``````

In python, one tends not to use the actual indexes in a list very often. Try a for-loop instead, plus a check to see whether the trend changed or not (this treats zero as a distinct trend from positive or negative - you can pretty simply change `same_direction` to group it one way or the other):

``````def same_direction(num1, num2):
# both numbers are positive, both are negative, or both are zero
return ((num1 > 0 and num2 > 0) or
(num1 < 0 and num2 < 0) or
(num1 == num2))

numbers = [1, 2, -1, -2, 4, 5]
result = [[]] #list with one sublist ready
last_number = 0
for num in numbers:
if same_direction(num, last_direction):
# No need for a new sublist, put new number in last sublist
result[-1].append(num)
else:
# trend changed, new sublist and put the number in it
result.append([num])
``````

If change in trends always go through the sign change, you can "group" items based on a sign using `itertools.groupby()`:

``````>>> from itertools import groupby
>>>
>>> [list(v) for _, v in groupby(numbers, lambda x: x < 0)]
[[1, 2], [-1, -2], [4, 5]]
``````

We are using `_` as a variable name for a "throw-away" variable since we don't need the grouping key in this case.

Here is my solution:

``````numbers = [1,2,-1,-2,4,5, 3, 2]

subset = []
subset_list = []
subset.append(numbers)

forward = 1

for i in range(0, len(numbers) - 1):
if ( forward == 1 ):
if numbers[i] <= numbers[i+1]:
subset.append(numbers[i+1])
else:
subset_list.append(subset)
subset = []
subset.append(numbers[i+1])
forward = 0
else:
if numbers[i] >= numbers[i+1]:
subset.append(numbers[i+1])
else:
subset_list.append(subset)
subset = []
subset.append(numbers[i+1])
forward = 1

subset_list.append(subset)

print(*subset)
print(*subset_list)
``````

Unfortunately, I only have python 3 on my system so my answer is in python 3.