【问题标题】:Python question -- lambda version of a recursive combinations functionPython问题——递归组合函数的lambda版本
【发布时间】:2020-05-31 20:07:44
【问题描述】:

好的,所以我有以下简单的 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。当不涉及递归时,我通常很擅长这个游戏,所以我只是想了解我在这里缺少什么。

【问题讨论】:

  • 您的问题的目标是什么?使用lambda 编写函数?使用列表推导编写函数?请注意,lambda 表达式通常不适合递归,因为递归本质上依赖于 按名称 调用函数——lambda 的重点是创建未命名的函数。您可以将lambda 分配给一个名称,但这违背了目的。
  • += 就像 list.extend(),它会扁平化你的列表,不像你的列表组合
  • @MisterMiyagi 根据我最初的问题,目标只是增加我自己对递归函数和列表理解的理解。

标签: python python-3.x lambda combinations permutation


【解决方案1】:

如果您的目标是将函数重写为 lambda one-liner,您可以使用 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:]))]

【讨论】:

  • 哇,速度如此之快!此外,我完全理解经典函数如何更好地用于生产代码。这是为了我自己的理解,主要是为了当我在野外遇到这样的事情时我不会感到困惑,因为并非我最终排除故障的所有内容都是可读的。让我稍微研究一下,但我认为这正是我正在寻找的东西。
  • 好吧... sum() 将展平一个列表,使得sum([[1, 2], [3, 4]], []) == [] + [1, 2] + [3, 4] ...我觉得我知道这一点,但它并没有真正点击我如何在某些情况下使用它,比如直到现在。好东西。
【解决方案2】:

您的问题在于列表理解。

[[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 次梳子。

【讨论】:

  • 酷!就像你说的可能不像@andrej-kesely 的版本那样“最佳”,但你的回答肯定会更好地帮助我了解我失败的尝试有什么问题。很好的插图,非常有帮助,谢谢!
猜你喜欢
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 1970-01-01
  • 2016-07-26
  • 1970-01-01
  • 2015-01-27
  • 1970-01-01
相关资源
最近更新 更多