I could not come up with a better title for my question, sorry.
I have two lists of the same length, e.g.
a = [True, False, False, True, True, False, False, True]
b = [1, 2, 2, 1, 1, 3, 3, 2 ]
i j i' j'
I want to adjust list a in such a way that whenever there is a block of or a single False in list a going from index i to j, it is adjusted according to the following condition:
if b[i-1]==b[j+1]:
a[i:j+1]=[True]*(j-i+1)
in the above example there are two such blocks: i,j=1,2 and i',j'=5,6.
The result should be:
a = [True, True, True, True, True, False, False, True]
I wrote a solution with a for loop using ifs but that is too slow since I want to use it on very large lists.
a = [True, False, False, True, True, False, False, True]
b = [1, 2, 2, 1, 1, 3, 3, 2 ]
#Edit: the next two lines were originally and wrongly inside the for loop
moving=True
istart=1
for i,trp in enumerate((a)):
if trp==False:
if moving==False:
# if this condition holds, the particle just started a new move
istart = i
moving = True
else:
if moving==True:
# is this condition holds, the particle has stopped its move
moving = False
if b[i]==b[istart-1]:
# if this holds, a needs to be adjusted
a[istart:i]=[True]*(i-istart)
Any help would be greatly appreciated. (The comments and variable names are like that since it's for analyzing a physics simulations)
You can try this:
import itertools
a = [True, False, False, True, True, False, False, True]
b = [1, 2, 2, 1, 1, 3, 3, 2 ]
new_a = [(a, list(b)) for a, b in itertools.groupby(zip(a, b), key=lambda x:x[0])]
final_list = list(itertools.chain(*[[True]*len(b) if not a and new_a[i-1][-1][-1] == new_a[i+1][-1][-1] and i > 0 else [c for c, d in b] for i, [a, b] in enumerate(new_a)]))
Output:
[True, True, True, True, True, False, False, True]
Edit: test with new input:
a = [True, False, True]
b = [1, 3, 1]
new_a = [(a, list(b)) for a, b in itertools.groupby(zip(a, b), key=lambda x:x[0])]
final_list = list(itertools.chain(*[[True]*len(b) if not a and new_a[i-1][-1][-1] == new_a[i+1][-1][-1] and i > 0 else [c for c, d in b] for i, [a, b] in enumerate(new_a)]))
Output:
[True, True, True]
Code explanation:
itertools.groupby forms the consecutive blocks of True/False values into single lists. Then, final_list stores the result of iterating over the lists stored in new_a, creating a new sublist of True values if the sublist is composed entirely of False values if and only if the preceding and following values are the same. This is determined by using enumerate to garner the current index for each iteration. That index can then be used to access the preceding and following values via i-1, i+1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With