我有以下功能
def handle(x):
if is_odd(x):
return x * 3 + 1
return x // 2
我想重复运行它,将 handle(x) 返回的值送入自身,直到它返回 1
即handle(...handle(handle(handle(x)))...) 直到链中的其中一个返回 1
repeat(handle(x), lambda x: x != 1)
我想写这样的东西:
(let n = handle(x) until n != 1)
基本上我想存储 handle 的输出直到我得到 1。
expression(handle(10)) = [5,
16,
8,
4,
2,
1]
是否有与此等效的生成器表达式?或者我可以为此使用的 functools.repeat 方法?
需要说明的是,我想避免直接使用带有 yield 或递归的 for 循环。我想在内置功能中使用 python 来解决此问题,但不包括 for 循环/递归。
请您参考如下方法:
你可以使用 itertools.accumulate 和 itertools.takewhile,我猜:
from itertools import accumulate, takewhile, repeat
def collatz(n):
seq = accumulate(repeat(n), lambda x,_: handle(x))
return list(takewhile(lambda x: x!=1, seq)) + [1]
给出
>>> collatz(5)
[5, 16, 8, 4, 2, 1]
>>> collatz(17)
[17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
但我同意共同的观点,即我不明白这里的重点。甚至官方文档也列出了很多 recipes这对于处理非内置的可迭代对象很方便;我不明白为什么你不能只定义类似的东西
def repeat_until(fn, x, cond):
while True:
yield x
if cond(x): break
x = fn(x)
继续你的一天。我知道您曾说过出于某种原因您不想明确使用 yield,但仅仅因为您说您想要某些东西并不意味着您想要的东西有任何意义。 :-)
