Python 使用列表理解在递归函数中创建列表列表
我正在试验递归函数。我的目标是生产: 一个函数Python 使用列表理解在递归函数中创建列表列表,python,recursion,list-comprehension,Python,Recursion,List Comprehension,我正在试验递归函数。我的目标是生产: 一个函数组合,它生成所有加起来等于n的非递增序列 一些示例输入/输出: >>> 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],
组合
,它生成所有加起来等于n的非递增序列
一些示例输入/输出:
>>> 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或not)可以使用单个列表理解返回相同的结果,而不附加和扩展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.]]
返回[[i]如果i==n else[[i]+x表示组合中的x(n-i,min(n-i,i))]表示范围内的i(limit,0,-1)]
#列表变得更深:[[4]、[3,1]]、[[2,2]、[2[1,1]]、[[1[1,1]]]、[[1,1]]]]
返回[[i if i==n else([i]+x表示组合中的x(n-i,min(n-i,i)))表示范围内的i(limit,0,-1)]]
#括号解释为生成器:[[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
大小写移动到另一个分支中(为了可读性,这里使用helperitems
变量):
如果i==n
,这将导致循环迭代一次并生成一个空列表,因此可以有效地获得res.append([i])
然后可以将其简单地转换为列表理解(将项
内联到for
循环中):
你是否应该是另一回事;这几乎不容易阅读。将扩展转换为追加,并更容易探索如何转换:
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
大小写移动到另一个分支中(为了可读性,这里使用helperitems
变量):
如果i==n
,这将导致循环迭代一次并生成一个空列表,因此可以有效地获得res.append([i])
然后可以将其简单地转换为列表理解(将项
内联到for
循环中):
你是否应该是另一回事;这几乎不容易阅读。适用于您的最新编辑(括号)。非常感谢您周到的回复@brianpck:是的,我对此感到惊讶,因为a是Python语法中
表达式
规则的最顶层组件,这也是它的一部分。我将进一步了解这是一个问题的原因。在不太了解语法规则的情况下,似乎假设if
是条件列表理解语法的一部分,例如[I for I in x if I==1]
@brianpck:yup,这也是我得出的结论:-D我的错误在于循环语法的,而不是你最近编辑的.Works(括号)。非常感谢您周到的回复@brianpck:是的,我对此感到惊讶,因为a是Python语法中表达式
规则的最顶层组件,这也是它的一部分。我将进一步了解这是一个问题的原因。在不太了解语法规则的情况下,似乎假设if
是条件列表理解语法的一部分,例如[I for I in x if I==1]
@brianpck:yup,这也是我得出的结论:-D我的错误是循环语法的,而不是循环语法。
return [
[i] + x
for i in range(limit, 0, -1)
for x in ([[]] if i == n else combo(n - i, min(n - i, i)))]