我想找到所有5位数字的字符串,其中
l0=["123","567","451"]
l1=["234","239","881"]
l2=["348","551","399"]
因此应该产生:
['12348', '12399']
。
因此我编写了一个函数
is_successor(a,b)
来测试a和b是否重叠:
def is_successor(a:str,b:str)->bool:
"""tests if strings a and b overlap"""
return a[1:]==b[:2]
然后我可以通过编写这个嵌套循环/检查结构来实现我的目标,该结构基本上附加到前面的字符串并产生所有有效的字符串:
pres=[]
for c in l2:
for b in l1:
if is_successor(b,c):
for a in l0:
if is_successor(a,b):
pres.append(a[0]+b[0]+c)
pres
l2
-> l0
开始,因为在我的原始数据中,列表变得更长,索引越低,因此我可以通过这种方式尽早过滤掉更多案例。l0,l1,l2
的所有组合并同时检查所有项目 a,b,c
的连续性的单个循环可以工作,但它测试的不必要的组合比我当前的构造更多。问题:
如何提取这个嵌套循环和条件检查调用?有没有一种Python式的方法来捕获
for
-> is_successor()
的重复?
您可以通过以下方式重写它以处理任意数量的列表:
首先,将最后一个列表的元素放入具有 1 个元素的子列表中(这简化了进一步的处理)
ps = [[c] for c in l2]
print(ps) # [['348'], ['551'], ['399']]
接下来,对于剩余的每个列表,检查哪些元素与
ps
中的元素匹配,并将它们添加到匹配元素的开头。
for l in [l1, l0]:
ps = [[a] + p for a in l for p in ps if is_successor(a, p[0])]
print(ps) # [['123', '234', '348'], ['123', '239', '399']]
现在将最终的字符串从列表中组装回来
pres = []
for p in ps:
pres.append(p[0]) # add entire element from l0
for el in p[1:]:
pres[-1] += el[-1] # add last character from following lists
print(pres) # ['12348', '12399']
由于我们直接引用输入列表的唯一地方是
for l in [l1, l0]:
以及从最后一个列表创建初始列表,因此如果更新这些行,这将适用于任意数量的列表。