0

I'm trying to find the average length a list stays positive or negative.

For example, I have a list

new_list = [1,2,3,4,-1,-2,-3,1,2,-4,-5,-6,-8]

I want to return the average time the list is positive and negative

so positive would be 4 + 2 = (6 / 2) = 3

and negative would be 3 + 4 = (7 / 2) = 3.5

def maxPositiveRun(lst):
    count = 0
    maxVal = 0
    score_array = []
    for n in lst:
        if n > 0:
            count +=1
            if count > maxVal:
                maxVal = count
                score_array.append(maxVal)
        else:
            count = 0
    
    return score_array
print(maxPositiveRun(a))

I have this code, but the problem is it adds another number when count is greater than the max value so if the list looks like this

a = [23.45,-56.34,89.56,45.23,-89.65,-56.43, 5.67,4.56,45.67,56.78]

it's going to add 3 then 4. So I am getting [1,2,3,4] when it should really just be [1,2,4].

How do I return score_array which is an array consisting of maximumal lengths of all sub-arrays which consists only of consecutive positive elements ?

Asocia
  • 5,935
  • 2
  • 21
  • 46
Austin Johnson
  • 697
  • 11
  • 23
  • 3
    I don't understand how your examples connected to question title. At all it's not clear what're you trying to do. – Olvin Roght Jun 24 '20 at 18:00
  • From what I understood, he is trying to compute the number of times the list contains consecutive positive numbers and then divide it by the number of times this occurs. That is why in the first example, the 4 corresponds to the 1 2 3 4 in the beginning of the list and the 2 corresponds to the 1 2 later. – Ozzy08 Jun 24 '20 at 18:10
  • Why are you trying to find `maxPositiveRun`? Shouldn't you be searching for _all_ positive runs? https://ideone.com/VBGwd9 – 001 Jun 24 '20 at 18:12
  • @OlvinRoght I have modified the question and now would probably make more sense – Abhishek Bhagate Jun 24 '20 at 18:26

2 Answers2

2

To get the right result, there should be slight modification to your code which I have made below.

Code -

def maxPositiveRun(lst):
    maxVal = 0           # Note that you didn't need count, you could do it with just one variable 
    score_array = []
    for n in lst:
        if n > 0:
            maxVal +=1
        else:
            # Append maxVal to array only when current element is negative and your positive streak(maxVal) is greater than 0
            if(maxVal>0):
                score_array.append(maxVal)
            maxVal = 0
    # Same as above. You need to check once after you have traversed the whole list
    if(maxVal>0):
        score_array.append(maxVal)
    
    return score_array
    
a = [23.45,-56.34,89.56,45.23,-89.65,-56.43, 5.67,4.56,45.67,56.78]    
print(maxPositiveRun(a))

Output :

[1, 2, 4]

Explanation

What you were doing in your code was to append the maxVal to the list every time you encountered a positive integer. This is probably not what you want.

  • You are looking to get the max possible streak of consecutive positive elements.
  • So, you should append the maxVal to the list only when you encounter a negative integer. This is the time when your consecutive element streak will potentially be the maximum
  • There can also be consecutive negative elements and we don't want to append the maxVal in this case. So, we check if maxVal > 0 and only append it if the condition is True. Else we know that there's no consecutive positive element streak.
  • After we end the loop ends, we must do another check if maxVal > 0. This will be the case when your list ends with a positive element streak.

Hope this helps !

Abhishek Bhagate
  • 5,583
  • 3
  • 15
  • 32
2

You can use itertools.groupby to shorten your code to just a few lines:

from collections import defaultdict
from itertools import groupby

a = [23.45, -56.34, 89.56, 45.23, -89.65, -56.43, 5.67, 4.56, 45.67, 56.78]
counter = defaultdict(list)

for k, g in groupby(a, lambda num: "pos" if num >= 0 else "neg"):
    counter[k].append(len(list(g)))

for k in ('pos', 'neg'):
    run = counter[k]
    print("{} run:".format(k), run)
    print("average is:", sum(run) / len(run))

Output:

pos run: [1, 2, 4]
average is: 2.3333333333333335
neg run: [1, 2]
average is: 1.5
Asocia
  • 5,935
  • 2
  • 21
  • 46