我正在尝试递归函数。我的目标是制作:
一个函数
combo
,它生成所有非增加的系列,加起来为
一些样本输入/输出:
>>> print (combo(3))
[[3], [2, 1], [1, 1, 1]]
>>> print (combo(4))
[[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]
>>> print (combo(5))
[[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]]
经过大量的反复试验后,我想出了以下功能,完全符合我的要求:
def combo(n, limit=None):
if not limit:
limit = n
# return [ LIST COMPREHENSION HERE ]
res = []
for i in range(limit, 0, -1):
if i == n:
res.append([i])
else:
res.extend([i] + x for x in combo(n - i, min(n - i, i)))
return res
我的问题:是否有办法(pythonic与否)使用单个列表理解返回相同的结果,而不附加并扩展res
?
以下是我尝试过的两件事,以及他们的错误结果:
return [[i] if i == n else [[i] + x for x in combo(n - i, min(n - i, i))] for i in range(limit, 0, -1)]
# lists get deeper: [[4], [[3, 1]], [[2, 2], [2, [1, 1]]], [[1, [1, [1, 1]]]]]
return [[i if i == n else ([i] + x for x in combo(n - i, min(n - i, i))) for i in range(limit, 0, -1)]]
# parentheses interpreted as generator: [[4, <generator object combo.<locals>.<listcomp>.<genexpr> at 0x01D84E40>, etc.]]
我意识到答案可能非常难看,但我已经花了足够的时间尝试,我只是想知道它是否可能。
答案 0 :(得分:4)
将扩展转换为附加,然后更容易理解如何转换它:
res = []
for i in range(limit, 0, -1):
if i == n:
res.append([i])
else:
# this is the generator expression pulled out of the res.extend() call
for x in combo(n - i, min(n - i, i)):
res.append([i] + x)
您现在可以将i == n
案例移到另一个分支中(为了便于阅读,请使用助手items
变量):
res = []
for i in range(limit, 0, -1):
items = [[]] if i == n else combo(n - i, min(n - i, i))
for x in items:
res.append([i] + x)
如果i == n
,这会导致循环迭代一次并产生一个空列表,因此您可以有效地获得res.append([i])
。
然后,这可以简单地转换为列表理解(将items
内联到for
循环中):
return [
[i] + x
for i in range(limit, 0, -1)
for x in ([[]] if i == n else combo(n - i, min(n - i, i)))]
是否应是另一回事;这几乎不容易阅读。