Home > Back-end >  If True: turn following values to True in list of booleans until nth position after True is reached
If True: turn following values to True in list of booleans until nth position after True is reached

Time:09-14

I have a list of booleans

l = [False, False, False, True, False, False, False]

that I want to turn into

l_new = [False, False, False, True, True, True, False]

That means, whenever there is a True in my list I want to switch the two (for example) following values to true. My solution is

def lagged_effect(l, lag):
    l_new = []
    L_iter = iter(l)
    for elem in L_iter:
        if elem == True:
            l_new.extend([True]*lag)
            if lag == 1:
                next(L_iter)
            if lag == 2:
                next(L_iter)
                next(L_iter)
            if lag == 3:
                next(L_iter)
                next(L_iter)
                next(L_iter)
            if lag == 4:
                next(L_iter)
                next(L_iter)
                next(L_iter)
                next(L_iter)
            if lag > 4:
                print("not defined")
        if elem == False:
            l_new.append(False)
    return l_new
    print(l_new)
lagged_effect(l, lag=2)

Since I want to implement this more often, I was wondering if there might be a more compact and efficient solution. Especially the next implementation annoys me.

CodePudding user response:

Using list shift and zip with boolean or

l = [False, False, False, True, False, False, False]

out = [x or y or z for x, y, z in zip(l, [False]   l, [False]*2   l)]
print(out)
[False, False, False, True, True, True, False]

Option for any lag

lag = 4
l = [False, False, False, True, False, False, False, False, False, True, False, False, False, False, True]
out = [bool(sum(z)) for z in zip(*[[False] * n   l for n in range(lag   1)])]
print(out)
[False, False, False, True, True, True, True, True, False, True, True, True, True, True, True]

CodePudding user response:

You can write a custom function:

l = [False, False, False, True, False, False, False]

def lag_true(l, lag=2):
    out = []
    last = 0
    for v in l:
        if v:                # if True, set up last to lag value
            last = lag
            out.append(True)
        elif last:           # if last (>0, implicit)
            out.append(True) # add True
            last -= 1        # decrease last
        else:                # we have a False and are far from last True
            out.append(False)
    return out

lag_true(l)
# [False, False, False, True, True, True, False]

lag_true(l, lag=3)
# [False, False, False, True, True, True, True]

Vectorial alternative using

import pandas as pd

LAG = 2

out = pd.Series(l).rolling(LAG 1, min_periods=1).max().astype(bool).to_list()
# [False, False, False, True, True, True, False]

CodePudding user response:

This is a possible solution:

l_new = l.copy()
for i in range(len(l) - 2):
    if l[i]: l_new[i   1] = l_new[i   2] = True

l_new[-1] = True if len(l) > 1 and l[-2] else l_new[-1]
  • Related