如何获取一个集合的所有子集?(幂集)

202

给定一个集合

{0, 1, 2, 3}

如何生成子集:

[set(),
 {0},
 {1},
 {2},
 {3},
 {0, 1},
 {0, 2},
 {0, 3},
 {1, 2},
 {1, 3},
 {2, 3},
 {0, 1, 2},
 {0, 1, 3},
 {0, 2, 3},
 {1, 2, 3},
 {0, 1, 2, 3}]

3
对于基于约束的因果发现算法,需要通过对所有涉及变量的可能子集进行条件独立性检验。我还遇到了在计算布尔函数的傅里叶级数时需要使用幂集。这显然只是冰山一角。 - Nazaal
2
@X10D 询问幂集的应用就像询问子集的应用一样,这是一个基本的数学概念。如何使用它取决于您。我曾尝试过使用它来尝试各种事物的组合。假设您的集合包含动作,您想测试所有可能的动作子集。那么迭代幂集就会感觉很自然。 - DustByte
32个回答

5
我知道这已经太晚了。
已经有许多其他解决方案,但是...
def power_set(lst):
    pw_set = [[]]

    for i in range(0,len(lst)):
        for j in range(0,len(pw_set)):
            ele = pw_set[j].copy()
            ele = ele + [lst[i]]
            pw_set = pw_set + [ele]

    return pw_set

4

使用空集,它是所有子集的一部分,可以使用以下内容:

def subsets(iterable):
    for n in range(len(iterable) + 1):
        yield from combinations(iterable, n)

4

我只想提供最易懂的解决方案,即反代码高尔夫版本。

from itertools import combinations

l = ["x", "y", "z", ]

def powerset(items):
    combo = []
    for r in range(len(items) + 1):
        #use a list to coerce a actual list from the combinations generator
        combo.append(list(combinations(items,r)))
    return combo

l_powerset = powerset(l)

for i, item in enumerate(l_powerset):
    print "All sets of length ", i
    print item

结果

所有长度为0的集合

[()]

所有长度为1的集合

[('x',), ('y',), ('z',)]

所有长度为2的集合

[('x', 'y'), ('x', 'z'), ('y', 'z')]

所有长度为3的集合

[('x', 'y', 'z')]

有关更多信息,请参见itertools文档,以及维基百科词条幂集


3
from itertools import combinations
def subsets(arr: set) -> list:
   subsets = []
   [subsets.extend(list(combinations(arr,n))) for n in range(len(arr))]
   return subsets 

a = {1,2,3}
print(subsets(a))

输出:

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

对于排序子集,我们可以这样做:
# sorted subsets
print(sorted(subsets(a)))

输出:

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

2
def powerSet(s):
    sets = [[]]
    for i in s:
        newsets = []
        for k in sets:
            newsets.append(k+[i])
        sets += newsets
    return sets

对于那些想要简单回答的人,首先编写代码。我在这里有一个好的解释:https://leetcode.com/problems/subsets/solutions/3138042/simple-python-solution/

但简短的答案是,你从空集合开始,即“sets = [[]]”。我建议在“for i in s”下面放置一个打印语句,即“print(sets)”,看到它在每个元素i中都会增加一倍。


+1,因为这是第一个不需要len(s)并且可以在不预先实现整个列表的情况下流式传输其答案的实现。它还以一种仅在生成先前答案的所有组合之后从s中提取新项的方式构建组合--也适用于流式传输!而且,它不是递归的!唯一需要更改的是在“sets + = newsets”之后(在相同的缩进处)添加“yield from newsets”,并消除最后的“return sets”。 - Eric Zinda

2

快速复习一下幂集!

一个集合X的幂集,就是包含X所有子集(包括空集)的集合。

例如,令X = (a,b,c)

幂集= { { a , b , c } , { a , b } , { a , c } , { b , c } , { a } , { b } , { c } , { } }

以下是另一种找到幂集的方法:

def power_set(input):
    # returns a list of all subsets of the list a
    if (len(input) == 0):
        return [[]]
    else:
        main_subset = [ ]
        for small_subset in power_set(input[1:]):
            main_subset += [small_subset]
            main_subset += [[input[0]] + small_subset]
        return main_subset

print(power_set([0,1,2,3]))

感谢原作者的贡献


2
如果您想要任意特定长度的子集,可以按照以下方式操作:
from itertools import combinations
someSet = {0, 1, 2, 3}
([x for i in range(len(someSet)+1) for x in combinations(someSet,i)])

更一般地,对于任意长度的子集,您可以修改范围参数。输出为:
[(),(0,),(1,),(2,),(3,),(0,1),(0,2),(0,3),(1,2),(1,3),(2,3),(0,1,2),(0,1,3),(0,2,3),(1,2,3),(0,1,2,3)]

2
你可以这样做:
def powerset(x):
    m=[]
    if not x:
        m.append(x)
    else:
        A = x[0]
        B = x[1:]
        for z in powerset(B):
            m.append(z)
            r = [A] + z
            m.append(r)
    return m

print(powerset([1, 2, 3, 4]))

输出:

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

1
我可以建议一下,当您发布代码解决方案时,请友善地给出详细的解释,说明代码正在做什么以及为什么使用这种或那种方法来解决问题。新手编程者不应该只是看着代码块并复制/粘贴它,而不知道代码正在做什么以及为什么这样做。感谢您的加入和欢迎来到Stackoverflow。 - Yokai
一个非常出色且递归的答案。 - John

1

使用递归获取所有子集。疯狂的一行代码。

from typing import List

def subsets(xs: list) -> List[list]:
    return subsets(xs[1:]) + [x + [xs[0]] for x in subsets(xs[1:])] if xs else [[]]

基于 Haskell 解决方案。
subsets :: [a] -> [[a]]
subsets [] = [[]]
subsets (x:xs) = map (x:) (subsets xs) ++ subsets xs

NameError: name 'List' is not defined - 4LegsDrivenCat
@4LegsDrivenCat 我已经添加了 List 导入。 - Paweł Rubin

1
def findsubsets(s, n): 
    return list(itertools.combinations(s, n)) 

def allsubsets(s) :
    a = []
    for x in range(1,len(s)+1):
        a.append(map(set,findsubsets(s,x)))      
    return a

仅提供代码的答案被认为是低质量的:请确保提供解释您的代码是如何解决问题的。如果您在帖子中添加更多信息,将有助于提问者和未来的读者。请参阅解释完全基于代码的答案 - Calos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接