Sum of segments that satisfy condition in list

Viewed 70

How do I create a new list containing sum of segments where the True elements within the main_list consecutively repeat for at least 3 times or more (min_segment=3)?

> main_list = [True, True, False, False, True, True, True, True, True, False, False, True, True, True]  
> min_segment=3

The expected answer should be:

> true_sum = [5, 3]
> #repeating segment at index 4 and contains 5 consecutive True elements, and next repeating segment at index 11 containing 3 True elements. Both segments are greater or equal to `min_segment` so are included in the `true_sum` list. 
> #the first repeating True segment starts at index 0 but contains 2 elements from main_list which is less than the `min_segment`, so is excluded from the `true_sum` list.

I need a simple code that does not require the use of numpy or groupby.

So far, my code shows the sum for all repeating True segments and does not account for the condition to only include the sum of segments with at least 3 or more True elements (min_segment=3).

> count = 0
> true_sum = []
> for v in main_list:
    if v:
        count += 1
    elif count:
        true_sum.append(count)
        count = 0
> if count:
        true_sum.append(count)

This gives an incorrect list of where the 2 should have been excluded:

> true_sum = [2,5,3]
2 Answers

This is an answer greatly inspired by Paul's code, I just removed the function definition and tweaked it to make it work in a couple of specific cases:

min_segment = 3

lengths = []
length = 0
prev_value = False

for value in main_list:

    if value:
        length += 1

    elif prev_value and not value:
        if length > min_segment:
            lengths.append(length)
        length = 0

    prev_value = value

if length >= min_segment:
    lengths.append(length)

Since you explicitly don't want a groupby solution, here's a simple generator. Not a huge fan of this solution, however, because I'm repeating myself in a couple places. Open to suggestions for improvement:

def segment_sums(segments, min_segments=3):

    prev_segment = None
    curr_sum = 1

    for segment in segments:
        if segment == prev_segment:
            curr_sum += 1
        else:
            if curr_sum >= min_segments:
                yield curr_sum
            prev_segment = segment
            curr_sum = 1
    if curr_sum >= min_segments:
        yield curr_sum

segments = [True, True, False, False, True, True, True, True, True, False, False, True, True, True]
print(list(segment_sums(segments)))
Related