Home > Back-end >  Detect alternating values in a list around 0?
Detect alternating values in a list around 0?

Time:10-22

Is there a short way to detect the longest sublist with alternative signs within a list?

For instance:

my_list = [-1, -0.5, 1, -3, 4, 5, 5, -1]

returning 4 starting from -0.5 to 4?

This is what I have written so far but I feel there is room for something much shorter.

import numpy

my_list = [-1, -0.5, 1, -3, 4, 5, 5, -1]

# function that detects whether a list has alternate signs
# https://stackoverflow.com/questions/6451514/detect-alternating-signs
def is_alternating_signs(a):
    return numpy.all(numpy.abs(numpy.diff(numpy.sign(a))) == 2)

# getting all sublists from the main list
sublists = []
for i in range(len(my_list)   1):
      for j in range(i   1, len(my_list)   1):
          sublists.append(my_list[i:j])

# detecting the longest sublist with alternate signs
max_list = 0
for sublist in sublists:
      if is_alternating_signs(sublist) and len(sublist) > max_list:
          max_list = len(sublist)
print(max_list)

CodePudding user response:

Use zip to compare the current element with the next one:

maxlen = 1
curlen = 1
for i, j in zip(l, l[1:]):

    # if one conditions match
    # increment curlen by 1
    if (i < 0 and j > 0) or (i > 0 and j < 0):
        curlen  = 1

    # break the alternative sign
    # keep the highest value between maxlen and curlen
    # reset curlen to 1
    else:
        maxlen = max(maxlen, curlen)
        curlen = 1
maxlen = max(maxlen, curlen)

Output:

>>> maxlen
4

CodePudding user response:

What about a single pass?

def find_largest_alternating_subseq_size(seq):
    last_x = 0 
    size = 1 
    max_size = 0 
    for i, x in enumerate(seq): 
        if last_x * x < 0: 
            size  = 1 
        else:
            if size > max_size: 
                max_size = size
            size = 1 
        last_x = x
    return max_size


find_largest_alternating_subseq_size(my_list)
# 4
  • Related