Erdos_95
Erdos_95

Reputation: 9

Is there an algorithm to split a list of numbers into smaller lists according to the number's sign?

I am trying to build an algorithm with the following capability:

Input: [1,3,4,5,-1,-2,-3,3,4,6,-1,-2] --------> Output: [1,3,4,5], [-1,-2,-3], [3,4,6], [-1,-2]

Input: [1,2,-3,-4,1,2,-5,-6,-7,1,2,-1] --------> Output: [1,2], [-3,-4], [1,2], [-5,-6,-7], [1,2], [-1]

Input: [-1,2,-1,2] --------> Output: [-1], [2],[-1],[2]

I want to take a list of numbers as input and then my desired output is to get smaller lists of numbers such that each smaller list contains numbers with same sign while preseving the order of the original list.

This is the code that I had written so far:

def sign_function(number):
    if number >= 0:
        return True
    else:
        return False
    
def builiding_sequences(numbers):
    sequences = []
    indexes = len(numbers)-1
    i = 0
    while i < indexes:
        sequence = []
        sequence.append(numbers[i])
        while True:
            if  sign_function(numbers[i]) == sign_function(numbers[i + 1]):
                sequence.append(numbers[i+1])
                i = i + 1
            else:
                i = i + 1
                break
        sequences.append(sequence)
    return sequences

This two functions get the work done as long as I do not work with the complete set of original values hence the reason why indexes is equal to len(numbers)-1, I am trying to get a algorithm with the capability of performing this routine with the complete set of original values in the input list. Thank you in advance!

Upvotes: 0

Views: 72

Answers (4)

KnowledgeGainer
KnowledgeGainer

Reputation: 1097

def check_numbers(number1,number2):
    if (number1 >= 0 and number2 >=0) or (number1 < 0 and number2 <0) :
        return True
    else:
        return False
    
def builiding_sequences(numbers):
    seq = []
    j=0
    num_len = len(numbers)
    for i in range(num_len-1):
      if check_numbers(numbers[i],numbers[i+1]):
        continue
      else:
        seq.append(numbers[j:i+1])
        j=i+1
    seq.append(numbers[j:])
    return seq
    
print(builiding_sequences([-3,1,3,4,5,-1,-2,-3,3,4,6,-1,-2]))
print(builiding_sequences([1,2,-3,-4,1,2,-5,-6,-7,1,2,-1]))
print(builiding_sequences([-1,2,-1,2]))

Upvotes: 0

Aditya Anand
Aditya Anand

Reputation: 3

lis = [1,3,4,5,-1,-2,-3,3,4,6,-1,-2]
flag,ans=0,[]

for i in range(len(lis)):
    if flag>=0 and lis[i]>=1:  # if previous was no trend (flag=0) or positive trend and curr element is also positive
        ans.append(lis[i])
        flag=1
    elif flag<=0 and lis[i]<=-1:   # if previous was no trend (flag=0) or negative trend and curr element is also negative
        ans.append(lis[i])
        flag=-1
    else:
        print(ans)  # print ans, flag = 0 means no trend
        ans.clear()
        ans.append(lis[i])
        flag=0
if ans:           # if ans is not empty print
    print(ans)

Upvotes: 0

Woodford
Woodford

Reputation: 4449

>>> L = [1,3,4,5,-1,-2,-3,3,4,6,-1,-2]
>>> [list(x[1]) for x in itertools.groupby(L, lambda x: x<0)]
[[1, 3, 4, 5], [-1, -2, -3], [3, 4, 6], [-1, -2]]

Upvotes: 2

asongtoruin
asongtoruin

Reputation: 10359

The standard library module itertools has a groupby method (docs) that I think would suit your use case here. It groups values together by applying some function, returning the result of the function and then the values themselves (as a grouper, which we want to convert to a list). So, in your case you'd need:

from itertools import groupby

def sign_function(number):
    return number >= 0

example = [1, 3, 4, 5, -1, -2, -3, 3, 4, 6, -1, -2]
result = [list(g) for k, g in groupby(example, sign_function)]

I've also simplified your sign_function slightly, as a one-liner will suffice.

Upvotes: 3

Related Questions