Python子集递归函数的这两个代码有什么区别?

What is the difference between these two codes of Python subset recursion function?

def all_subsets(s):
    if len(s) == 1: return [[], s]
    else:
        sets = all_subsets(s[:-1])
        for e in sets:
            return sets + [e + [s[-1]]]

我试过上面的代码,但它只 returns [[], [1], [2], [3]]

所以我不小心尝试了下面的 one liner return 语句:

def all_subsets(s):
    if len(s) == 1: return [[], s]
    else:
        sets = all_subsets(s[:-1])
        return sets + [e + [s[-1]] for e in sets]

它奏效了。我不明白在 return 语句中使用 for 循环是如何使这段代码工作的;请帮助我了解它是如何工作的,因为我已经尝试在可视化工具上运行它,但我仍然不明白。

并且,如果可能的话,如果您能在不使用单行 return 语句的情况下让我的第一个代码正常工作。

提前百万感谢

第一种情况未能return您预期的结果,因为 return 语句 循环中。基本上,代码将在 for 循环的第一次迭代中退出函数(仅对第一个子集求和,然后 returning 结果并结束函数调用)...第二个示例对所有子集求和 然后 return结果。

第一种情况的问题是它 returns 第一次出现在 for 循环中。对于第一个 e,它 returns 然后退出循环。要修复您的代码:

def all_subsets(s):
    if len(s) == 1: return [[], s]
    else:
        sets = all_subsets(s[:-1])
        returnset = []
        for e in sets:
            returnset.extend([e,e + [s[-1]]])
        return returnset

s= [1,2,3]
print all_subsets(s)

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

虽然我更喜欢列表理解版本。

除了有关您的代码的问题外,还有一种获取所有子集列表的方法:

(来自:https://wiki.python.org/moin/Powerful%20Python%20One-Liners

这是一个工作函数,用于 return 任何给定序列的所有子集的列表:

#!/python
f = lambda l: reduce(lambda z, x: z + [y + [x] for y in z], l, [[]])

...请注意,此 lambda 是递归定义的(就像在您的函数中一样)。

对于 n 个元素,子集集的大小增长为 2**n 也是毫无意义的。换句话说,对于一组 10 个元素,子集集有 1024 个元素。

思考和建模的方式是考虑从 0 到 2**n 的所有二进制数...如果您枚举所有这些位串并将每个位串视为 "mask" 将哪些项目包含在相应的子集中,那么您会发现您已经涵盖了从空集 (0) 到完整原始集 (11111...1111) 的所有可能子集。

这意味着您可以 return 序列的 "nth" "subset" 而无需枚举所有中间的 "subsets" (恐慌引号,因为数学上是一个集合是无序的;但是这种处理依赖于将位串映射到一个序列...在 "set" 被有序处理)。