避免字符串连接的嵌套循环的Pythonic方法

问题描述 投票:0回答:1

我想找到所有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()
的重复?

python python-3.x
1个回答
0
投票

您可以通过以下方式重写它以处理任意数量的列表:

首先,将最后一个列表的元素放入具有 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]:
以及从最后一个列表创建初始列表,因此如果更新这些行,这将适用于任意数量的列表。

© www.soinside.com 2019 - 2024. All rights reserved.