使用列表推导在递归函数中创建列表列表

时间:2016-10-05 15:14:23

标签: python recursion list-comprehension

我正在尝试递归函数。我的目标是制作:

  

一个函数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.]]

我意识到答案可能非常难看,但我已经花了足够的时间尝试,我只是想知道它是否可能。

1 个答案:

答案 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)))]

是否是另一回事;这几乎不容易阅读。