The Python Oracle

How can i return the longest continuous occurrence of "True" in Boolean, and replace other True with False?

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Melt

--

Chapters
00:00 Question
01:09 Accepted answer (Score 3)
02:13 Answer 2 (Score 1)
03:06 Thank you

--

Full question
https://stackoverflow.com/questions/5630...

Accepted answer links:
[more_itertools.run_length]: https://more-itertools.readthedocs.io/en...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #numpy #moreitertools

#avk47



ACCEPTED ANSWER

Score 3


Below solution should work after using more_itertools.run_length.

Essentially, the logic is to find the length of longest subsequence of True, and the location of that index in result list
then count the total elements before and after that longest subsequence, then construct the resultant list of tuples accordingly.

import more_itertools as mit

a=[True, True, False, True , True, True, False]

result = list(mit.run_length.encode(a))

#Find the length of longest subsequence of True, and the location if that index in result
max_true_count = -1
max_true_idx  = -1
for idx, (val, count) in enumerate(result):
    if val and max_true_count < count:
        max_true_count = count
        max_true_idx = idx

#Find total elements before and after the longest subsequence tuple
elems_before_idx = sum((idx[1] for idx in result[:max_true_idx]))
elems_after_idx = sum((idx[1] for idx in result[max_true_idx+1:]))

#Create the output list using the information
output = [(False, elems_before_idx), (True, max_true_count), (False, elems_after_idx)]
print(output)

The output will be

[(False, 3), (True, 3), (False, 1)]



ANSWER 2

Score 2


Here's a vectorized one -

def keep_longest_true(a):
    # Convert to array
    a = np.asarray(a)

    # Attach sentients on either sides w.r.t True
    b = np.r_[False,a,False]

    # Get indices of group shifts
    s = np.flatnonzero(b[:-1]!=b[1:])

    # Get group lengths and hence the max index group
    m = (s[1::2]-s[::2]).argmax()

    # Initialize array and assign only the largest True island as True.
    out = np.zeros_like(a)
    out[s[2*m]:s[2*m+1]] = 1
    return out

def island_info(a):
    '''' Get island tuple info
    '''

    # Attach sentients on either sides w.r.t array start and end
    b = np.r_[~a[0],a,~a[-1]]

    # Get group lengths and group start elements
    lens = np.diff(np.flatnonzero(b[:-1] != b[1:]))
    grpID = np.resize([a[0],~a[0]],len(lens))

    # zip those two info for final o/p
    return zip(grpID,lens)

Sample run -

In [221]: a
Out[221]: [True, True, False, True, True, True, False]

In [222]: keep_longest_true(a)
Out[222]: array([False, False, False,  True,  True,  True, False])

In [223]: island_info(keep_longest_true(a))
Out[223]: [(False, 3), (True, 3), (False, 1)]