1

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[0])

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

Thanks!

-Jake

Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
Jake Schurch
  • 135
  • 1
  • 1
  • 8

5 Answers5

2

Here is a way to re-write this:


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


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

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)    

Israel Unterman
  • 13,158
  • 4
  • 28
  • 35
1

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.

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
1

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])
Vivian
  • 1,539
  • 14
  • 38
0

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[0]]
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)
Liam Kelly
  • 3,524
  • 1
  • 17
  • 41
  • Wow Liam thank you so much this works perfectly! After looking over your code vs mine; it looks like the reason that your's works is because you're evaluating everything within a single if statement whereas mine had two. I never thought to evaluate tmp as [n[i]] – Jake Schurch Aug 31 '16 at 18:07
  • Glad I could help. If you think my answer is the one that works, mark it as the answer. – Liam Kelly Aug 31 '16 at 23:14
0

Here is my solution:

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

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


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.