在列表中获取所有递归结果



我正在学习python递归。为了练习,我正在给出一个任务来查找列表的所有子集。例如函数:

subset([1,2)] should return [[1,2],[1],[2],[]]

我可以让我的函数在递归的帮助下打印这些结果

def subset(List):
print(List)
n = len(List)
if n > 2:
for i in range(n):
subset(List[:i]+List[i+1:])
if n == 2:
subset([List[0]])
subset([List[1]])
if n == 1:
subset([])
pass
L = [1,2]
test = subset(L)

打印语句打印:

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

我希望函数不打印,而是按照所需结果在列表中返回它。

我希望你对此的看法。

首先,如果您实际上不必自己实现它,标准库很乐意提供帮助。

但对于研究递归来说,这是一个有趣的问题,所以让我们仔细看看。

与这里类似,对于递归的复杂用途,a(一次进行多个递归调用,b(需要以某种方式"积累"结果,我的建议是编写一个递归生成器。您可以机械地转换它:

  • print替换为yield

  • yield from递归调用(正如我在另一个答案中指出的那样,对于不需要累积结果的情况,您通常希望return这些结果(。

然后从递归外部,您可以将结果收集到list中,或直接迭代它们。

但是,您的算法也存在一个问题:缺少两个或多个原始元素的结果将出现不止一次(正如您已经看到的那样(,因为它们的递归"路径"不止一个。您想要的算法是:

  • 递归获取不包含第一个元素的子集
  • 对于其中的每一个,发出两个结果:一个带有第一个元素的前缀,另一个没有

因此,我们将迭代结果,进行一些修改,并在该循环中yield,而不是yield from

将所有这些放在一起,它看起来像:

def power_set(items):
if not items: # empty set; base case for recursion.
yield items
return
# Pull off the first element,
first, *rest = items
# then iterate over the recursive results on the rest of the elements.
for without_first in power_set(rest):
yield [first] + without_first
yield without_first
# let's test it:
list(power_set([1,2,3]))
# [[1, 2, 3], [2, 3], [1, 3], [3], [1, 2], [2], [1], []]
# Good, just what we want - with no duplicates.

最新更新