我无法为我的问题想出更好的标题,抱歉。
我有两个相同长度的列表,例如
a = [True, False, False, True, True, False, False, True]
b = [1, 2, 2, 1, 1, 3, 3, 2 ]
i j i' j'
我想以这样的方式调整列表 a
,只要列表 a
中有一个 block 或一个 False
从索引i
到j
,根据以下条件调整:
if b[i-1]==b[j+1]:
a[i:j+1]=[True]*(j-i+1)
在上面的例子中有两个这样的 block :i,j=1,2
和 i',j'=5,6
。
结果应该是:
a = [True, True, True, True, True, False, False, True]
我使用 if
编写了一个带有 for
循环的解决方案,但是这太慢了,因为我想在非常大的列表中使用它。
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)
如有任何帮助,我们将不胜感激。 (注释和变量名是这样的,因为它是用于分析物理模拟的)
最佳答案
你可以试试这个:
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)]))
输出:
[True, True, True, True, True, False, False, True]
编辑:使用新输入进行测试:
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)]))
输出:
[True, True, True]
代码解释:
itertools.groupby
将 True
/False
值的连续 block 形成单个列表。然后,final_list
存储迭代存储在 new_a
中的列表的结果,如果子列表完全由以下内容组成,则创建 True
值的新子列表False
值当且仅当前后值相同时。这是通过使用 enumerate
为每次迭代获取当前索引来确定的。然后可以使用该索引通过 i-1
、i+1
访问前面和后面的值。
关于python - 根据另一个列表有效地调整 python 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48266566/