Python 如何使用递归根据谓词将序列插入列表列表
我目前正在练习递归,我经常遇到的一个问题是将序列切割成列表。我试图自己解决,但没有成功: 我的代码:Python 如何使用递归根据谓词将序列插入列表列表,python,list,Python,List,我目前正在练习递归,我经常遇到的一个问题是将序列切割成列表。我试图自己解决,但没有成功: 我的代码: def cut_sequence_at(seq, pred) -> list: if not seq: return [[]] if len(seq) == 1: return [seq] rest = cut_sequence_at(seq[1:], pred) if pred(seq[0]): return
def cut_sequence_at(seq, pred) -> list:
if not seq:
return [[]]
if len(seq) == 1:
return [seq]
rest = cut_sequence_at(seq[1:], pred)
if pred(seq[0]):
return [[seq[0]] + rest[0]] + rest[1:]
else:
return [[seq[0]]] + rest
# input
seq = [8,6,3,4,12,8,7,2,1]
pred = lambda x: x % 2 != 0
cut_sequence_at(seq, pred)
# Output
[[8], [6], [3, 4], [12], [8], [7, 2], [1]]
# Expected output
[[8, 6], [3, 4, 12, 8], [7, 2], [1]]
显然我的逻辑有问题,但我不知道如何解决。如果不使用非标准的lib模块,您将如何解决该问题?您可以使用next()
函数查找满足条件的第一个项目的位置。返回该部分,其余部分递归。找到断裂位置需要从第二个项目开始,这样您就不会生成空零件
def cut(seq,cond):
i = next((i for i, n in enumerate(seq[1:], 1) if cond(n)), None)
if i is None: return [seq] # no item meeting condition
return [seq[:i]] + cut(seq[i:], cond) # first part + recursion
seq = [8,6,3,4,12,8,7,2,1]
pred = lambda x: x % 2 != 0
print(cut(seq, pred))
[[8, 6], [3, 4, 12, 8], [7, 2], [1]]
最具python风格的解决方案是使用迭代解决方案,而不是递归解决方案。如果您想要一个遵循类似Lisp的head,tail方法的递归解决方案,最简单的方法是定义一个递归助手函数,该函数接受最终状态已确定的块列表、当前正在增长的块以及列表的其余部分。它检查列表其余部分的标题。如果满足谓词,则增长块(如果非空)被添加到已知块列表中,并初始化新的增长块。否则,头部会被钉在生长块的末端。这在理论上具有如下优势(如果python优化了尾部调用,这将很重要)
您的
else
子句总是创建一个列表列表,其中第一个元素是长度为1的列表。它有效!非常感谢。
def cut_sequence_at(seq, pred):
def helper(settled,active,rest):
if rest == []:
if active != []:
settled.append(active)
return settled
head, tail = rest[0],rest[1:]
if pred(head):
if active != []:
settled.append(active)
active = [head]
else:
active.append(head)
return helper(settled,active,tail)
return helper([],[],seq)
seq = [8,6,3,4,12,8,7,2,1]
pred = lambda x: x % 2 != 0
print(cut_sequence_at(seq, pred)) #[[8, 6], [3, 4, 12, 8], [7, 2], [1]]