Python问题-递归组合函数的lambda版本

问题描述 投票:1回答:2

好,所以我有以下简单的Python 3函数,可以完成应有的功能:

def comb(a):
    if len(a)==0:
        return[[]]
    else:
        p=[]
        for c in comb(a[1:]):
            p+=[c,c+a[:1]]      
        return p

正确产生

>>> comb([1,2,3])
[[], [1], [2], [2, 1], [3], [3, 1], [3, 2], [3, 2, 1]]

出于对更好地了解递归函数的渴望,我试图看看是否可以将这个简单的函数转换为lambda。我首先尝试的是以下版本的各种版本:

comb=lambda a:[[]]if len(a)==0 else[[c,c+a[:1]]for c in comb(a[1:])]

显然,这没有用。然后我退后一步,尝试更改原始函数的语法,例如:

def comb(a):
    return[[]]if len(a)==0 else[p for p in[[c,c+a[:1]]for c in comb(a[1:])]]

这也根本不起作用。我尝试了各种不同的安排,但无济于事。显然,原始函数是最有用和最容易阅读的,我只是在问这个问题,以更好地了解自己的python。在不涉及递归的情况下,我通常会很擅长这款游戏,所以我只是想了解我在这里缺少的内容。

python python-3.x lambda combinations permutation
2个回答
2
投票

如果您的目标是将函数重写为lambda一线式,则可以使用sum()来实现,例如:

comb = lambda a: [[]] if len(a)==0 else sum(([c,c+a[:1]] for c in comb(a[1:])), [])

print(comb([1, 2, 3]))

打印:

[[], [1], [2], [2, 1], [3], [3, 1], [3, 2], [3, 2, 1]]

注意:上面的解决方案不是很可读。经典功能更好。


感谢@Chris_Rands,使用itertools.chain解决方案:

from itertools import chain

comb = lambda a: [[]] if len(a)==0 else [*chain.from_iterable([c,c+a[:1]] for c in comb(a[1:]))]

0
投票

您的问题在于列表理解。

[[c,c+a[:1]]for c in l]是长度为len(l)的列表,其元素是具有2个元素的列表。您需要的是长度为2*len(l)的列表,这是此值的扁平版本。

comb=lambda a:[[]]if len(a)==0 else[c+a[:1]for c in comb(a[1:])] + comb(a[1:])

有效,但可能会得到改进,因为每次只需要1个时,它都会进行2次调用以进行梳理。

© www.soinside.com 2019 - 2024. All rights reserved.