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

时间:2009-09-26 22:11:20

标签: python set powerset

给定一组

{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}]

30 个答案:

答案 0 :(得分:76)

Python itertools page有一个powerset配方:

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

输出:

>>> list(powerset("abcd"))
[(), ('a',), ('b',), ('c',), ('d',), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd'), ('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'd'), ('b', 'c', 'd'), ('a', 'b', 'c', 'd')]

如果您不喜欢开头的空元组,则可以将range语句更改为range(1, len(s)+1)以避免0长度组合。

答案 1 :(得分:31)

这是更多关于powerset的代码。这是从头开始写的:

>>> def powerset(s):
...     x = len(s)
...     for i in range(1 << x):
...         print [s[j] for j in range(x) if (i & (1 << j))]
...
>>> powerset([4,5,6])
[]
[4]
[5]
[4, 5]
[6]
[4, 6]
[5, 6]
[4, 5, 6]

Mark Rushakoff的评论适用于此:“如果你不喜欢开头的空元组,那么。”你可以将范围语句更改为范围(1,len(s)+1)以避免0 -length combination“,除非在我的情况下,您将for i in range(1 << x)更改为for i in range(1, 1 << x)


回到这几年后,我现在写这样:

def powerset(s):
    x = len(s)
    masks = [1 << i for i in range(x)]
    for i in range(1 << x):
        yield [ss for mask, ss in zip(masks, s) if i & mask]

然后测试代码看起来像这样,说:

print(list(powerset([4, 5, 6])))

使用yield意味着您无需在单个内存中计算所有结果。预先假定主循环外的掩模是值得优化的。

答案 2 :(得分:14)

如果您正在寻找快速回答,我只是在谷歌搜索“python power set”并想出了这个:Python Power Set Generator

以下是该页面代码中的复制粘贴:

def powerset(seq):
    """
    Returns all the subsets of this set. This is a generator.
    """
    if len(seq) <= 1:
        yield seq
        yield []
    else:
        for item in powerset(seq[1:]):
            yield [seq[0]]+item
            yield item

可以这样使用:

 l = [1, 2, 3, 4]
 r = [x for x in powerset(l)]

现在r是您想要的所有元素的列表,可以进行排序和打印:

r.sort()
print r
[[], [1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 4], [1, 3], [1, 3, 4], [1, 4], [2], [2, 3], [2, 3, 4], [2, 4], [3], [3, 4], [4]]

答案 3 :(得分:10)

def powerset(lst):
    return reduce(lambda result, x: result + [subset + [x] for subset in result],
                  lst, [[]])

答案 4 :(得分:6)

对powerset进行了改进:

def powerset(seq):
    """
    Returns all the subsets of this set. This is a generator.
    """
    if len(seq) <= 0:
        yield []
    else:
        for item in powerset(seq[1:]):
            yield [seq[0]]+item
            yield item

答案 5 :(得分:4)

def get_power_set(s):
  power_set=[[]]
  for elem in s:
    # iterate over the sub sets so far
    for sub_set in power_set:
      # add a new subset consisting of the subset at hand added elem
      power_set=power_set+[list(sub_set)+[elem]]
  return power_set

例如:

get_power_set([1,2,3])

产量

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

答案 6 :(得分:3)

这可以很自然地通过itertools.product完成:

import itertools

def powerset(l):
    for sl in itertools.product(*[[[], [i]] for i in l]):
        yield {j for i in sl for j in i}

答案 7 :(得分:3)

我发现以下算法非常简单明了:

def get_powerset(some_list):
    """Returns all subsets of size 0 - len(some_list) for some_list"""
    if len(some_list) == 0:
        return [[]]

    subsets = []
    first_element = some_list[0]
    remaining_list = some_list[1:]
    # Strategy: get all the subsets of remaining_list. For each
    # of those subsets, a full subset list will contain both
    # the original subset as well as a version of the subset
    # that contains first_element
    for partial_subset in get_all_subsets(remaining_list):
        subsets.append(partial_subset)
        subsets.append(partial_subset[:] + [first_element])

    return subsets

生成powerset的另一种方法是生成所有具有n位的二进制数。作为电源设置,n位数的数量为2 ^ n。该算法的原理是元素可以存在或不存在于子集中,因为二进制数字可以是1或0而不是两者。

def power_set(items):
    N = len(items)
    # enumerate the 2 ** N possible combinations
    for i in range(2 ** N):
        combo = []
        for j in range(N):
            # test bit jth of integer i
            if (i >> j) % 2 == 1:
                combo.append(items[j])
        yield combo

我在参加MITx时发现了两种算法:6.00.2x计算思维和数据科学简介,我认为这是我所见过的最容易理解的算法之一。

答案 8 :(得分: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]))

全额归功于source

答案 9 :(得分:2)

TL; DR(直接进入简化)

我知道我之前已经添加了答案,但是我真的很喜欢我的新实现。我将一组作为输入,但是实际上它可以是任何迭代的,并且我将返回一组集合,即输入的幂集。我喜欢这种方法,因为它与power set(所有子集的)的数学定义更加一致。

def power_set(A):
    """A is an iterable (list, tuple, set, str, etc)
    returns a set which is the power set of A."""
    length = len(A)
    l = [a for a in A]
    ps = set()

    for i in range(2 ** length):
        selector = f'{i:0{length}b}'
        subset = {l[j] for j, bit in enumerate(selector) if bit == '1'}
        ps.add(frozenset(subset))

    return ps

如果您要确切地在答案中发布输出,请使用以下命令:

>>> [set(s) for s in power_set({1, 2, 3, 4})]
[{3, 4},
 {2},
 {1, 4},
 {2, 3, 4},
 {2, 3},
 {1, 2, 4},
 {1, 2},
 {1, 2, 3},
 {3},
 {2, 4},
 {1},
 {1, 2, 3, 4},
 set(),
 {1, 3},
 {1, 3, 4},
 {4}]

说明

众所周知,幂集的元素数为2 ** len(A),因此可以在for循环中清楚地看到。

我需要将输入(最好是集合)转换为列表,因为通过集合是唯一无序元素的数据结构,并且顺序对于生成子集至关重要。

selector是此算法的关键。请注意,selector的长度与输入集的长度相同,为了实现这一点,可以使用带填充的f字符串。基本上,这使我可以选择在每次迭代期间将添加到每个子集的元素。假设输入集包含3个元素{0, 1, 2},那么选择器将采用0到7(含)之间的值,二进制形式为:

000 # 0
001 # 1
010 # 2
011 # 3
100 # 4
101 # 5
110 # 6
111 # 7

因此,是否应添加原始集合的元素,每个位都可以用作指示符。查看二进制数字,然后将每个数字视为超集的元素,其中1表示应该添加索引j的元素,而0表示元素不应添加。

我正在使用集合推导在每次迭代时生成一个子集,并将该子集转换为frozenset,因此可以将其添加到ps(幂集)中。否则,我将无法添加它,因为Python中的集合仅包含不可变的对象。

简化

您可以使用一些python理解来简化代码,因此可以摆脱那些for循环。您也可以使用zip来避免使用j索引,代码最终将如下所示:

def power_set(A):
    length = len(A)
    return {
        frozenset({e for e, b in zip(A, f'{i:{length}b}') if b == '1'})
        for i in range(2 ** length)
    }

就是这样。我喜欢这种算法的原因是,它比其他算法更清晰,更直观,因为即使按预期运行,依靠itertools看起来也很神奇。

答案 10 :(得分:1)

我知道这为时已晚

已经有许多其他解决方案,但仍然...

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

答案 11 :(得分:1)

我只是想提供最易于理解的解决方案,即反码高尔夫版。

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')]

更多see the itertools docs,还有power sets

上的维基百科条目

答案 12 :(得分:1)

您可以这样做:

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]]

答案 13 :(得分:1)

也许这个问题越来越老了,但我希望我的代码能对某人有所帮助。

def powSet(set):
    if len(set) == 0:
       return [[]]
    return addtoAll(set[0],powSet(set[1:])) + powSet(set[1:])

def addtoAll(e, set):
   for c in set:
       c.append(e)
   return set

答案 14 :(得分:1)

使用软件包powerset()中的函数more_itertools

产生可迭代的所有可能子集

>>> list(powerset([1, 2, 3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

如果要设置,请使用:

list(map(set, powerset(iterable)))

答案 15 :(得分: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

答案 16 :(得分: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

答案 17 :(得分:0)

这是我的解决方案,在概念上与lmiguelvargasf的解决方案相似。

我说 -[数学项目]根据定义,幂集确实包含空集 -[个人品味],而且我不喜欢使用Frozenset。

因此,输入是列表,而输出将是列表。该功能可能会更早关闭,但是我喜欢将幂集的元素按字典顺序排序 ,这实际上意味着很好。

def power_set(L):
    """
    L is a list.
    The function returns the power set, but as a list of lists.
    """
    cardinality=len(L)
    n=2 ** cardinality
    powerset = []
    
    for i in range(n):
        a=bin(i)[2:]
        subset=[]
        for j in range(len(a)):
            if a[-j-1]=='1':
                subset.append(L[j])
        powerset.append(subset)
        
    #the function could stop here closing with
    #return powerset

    powerset_orderred=[]
    for k in range(cardinality+1):
        for w in powerset:
            if len(w)==k:
                powerset_orderred.append(w)
        
    return powerset_orderred

答案 18 :(得分:0)

如果您想要任何特定长度的子集,可以这样做:

select students.st_name as Students_Name,avg(Score) as Average, max(Score) as Maximum,subjects.sub_name as Max_Subject_name  
from marks 
join students on students.student_id=marks.st_id
join subjects on subjects.subject_id=marks.sub_id
join
(
select st_id,avg(score) as Average,max(score) as Maximum from  marks group by st_id
) as x  on x.st_id=marks.st_id
order by students.st_name,subjects.sub_name;

通常,对于任意长度的子集,您可以修改范围偏差。输出是

[(),(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)]

答案 19 :(得分:0)

我没有遇到过more_itertools.powerset函数,建议您使用它。我还建议不要使用itertools.combinations的输出的默认顺序,通常是要最小化位置之间的距离,并对项目子集进行排序,使子集之间的距离较短/高于/之前它们之间有较大距离的物品。

itertools recipes page显示它使用了chain.from_iterable

  • 请注意,此处的rbinomial coefficient下部的标准符号匹配,s在数学课本和计算器中通常称为n (“ n选择r”)
def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

这里的其他示例以{字典顺序}列出2元组的方式提供[1,2,3,4]的幂集(当我们将数字打印为整数时)。如果我在数字旁边写下数字之间的距离(即差异),则表明我的观点:

12 ⇒ 1
13 ⇒ 2
14 ⇒ 3
23 ⇒ 1
24 ⇒ 2
34 ⇒ 1

正确的子集顺序应该是先“耗尽”最小距离的顺序,例如:

12 ⇒ 1
23 ⇒ 1
34 ⇒ 1
13 ⇒ 2
24 ⇒ 2
14 ⇒ 3

在此处使用数字会使此顺序看起来“错误”,但是考虑一下字母["a","b","c","d"],这很清楚为什么对于按此顺序获得幂集很有用:

ab ⇒ 1
bc ⇒ 1
cd ⇒ 1
ac ⇒ 2
bd ⇒ 2
ad ⇒ 3

此效果在更多项目中更为明显,就我的目的而言,它使得能够有意义地描述Powerset的索引范围之间存在区别。

(在Gray codes等上写了很多关于组合语言学算法输出顺序的信息,我不认为这是附带问题)。

我实际上只是编写了一个相当复杂的程序,该程序使用此快速整数分区代码以正确的顺序输出值,但是后来我发现more_itertools.powerset,对于大多数使用情况,只使用这样的函数可能就可以了:

from more_itertools import powerset
from numpy import ediff1d

def ps_sorter(tup):
    l = len(tup)
    d = ediff1d(tup).tolist()
    return l, d

ps = powerset([1,2,3,4])

ps = sorted(ps, key=ps_sorter)

for x in ps:
    print(x)

()
(1,)
(2,)
(3,)
(4,)
(1, 2)
(2, 3)
(3, 4)
(1, 3)
(2, 4)
(1, 4)
(1, 2, 3)
(2, 3, 4)
(1, 2, 4)
(1, 3, 4)
(1, 2, 3, 4)

我写了一些更复杂的代码,可以很好地打印powerset(请参阅回购中的漂亮打印功能,我这里未包括这些功能:print_partitionsprint_partitions_by_lengthpprint_tuple)。

这一切都非常简单,但是如果您想要一些可以直接访问不同级别的Powerset的代码,它仍然可能有用:

from itertools import permutations as permute
from numpy import cumsum

# http://jeromekelleher.net/generating-integer-partitions.html
# via
# https://stackoverflow.com/questions/10035752/elegant-python-code-for-integer-partitioning#comment25080713_10036764

def asc_int_partitions(n):
    a = [0 for i in range(n + 1)]
    k = 1
    y = n - 1
    while k != 0:
        x = a[k - 1] + 1
        k -= 1
        while 2 * x <= y:
            a[k] = x
            y -= x
            k += 1
        l = k + 1
        while x <= y:
            a[k] = x
            a[l] = y
            yield tuple(a[:k + 2])
            x += 1
            y -= 1
        a[k] = x + y
        y = x + y - 1
        yield tuple(a[:k + 1])

# https://stackoverflow.com/a/6285330/2668831
def uniquely_permute(iterable, enforce_sort=False, r=None):
    previous = tuple()
    if enforce_sort: # potential waste of effort (default: False)
        iterable = sorted(iterable)
    for p in permute(iterable, r):
        if p > previous:
            previous = p
            yield p

def sum_min(p):
    return sum(p), min(p)

def partitions_by_length(max_n, sorting=True, permuting=False):
    partition_dict = {0: ()}
    for n in range(1,max_n+1):
        partition_dict.setdefault(n, [])
        partitions = list(asc_int_partitions(n))
        for p in partitions:
            if permuting:
                perms = uniquely_permute(p)
                for perm in perms:
                    partition_dict.get(len(p)).append(perm)
            else:
                partition_dict.get(len(p)).append(p)
    if not sorting:
        return partition_dict
    for k in partition_dict:
        partition_dict.update({k: sorted(partition_dict.get(k), key=sum_min)})
    return partition_dict

def print_partitions_by_length(max_n, sorting=True, permuting=True):
    partition_dict = partitions_by_length(max_n, sorting=sorting, permuting=permuting)
    for k in partition_dict:
        if k == 0:
            print(tuple(partition_dict.get(k)), end="")
        for p in partition_dict.get(k):
            print(pprint_tuple(p), end=" ")
        print()
    return

def generate_powerset(items, subset_handler=tuple, verbose=False):
    """
    Generate the powerset of an iterable `items`.

    Handling of the elements of the iterable is by whichever function is passed as
    `subset_handler`, which must be able to handle the `None` value for the
    empty set. The function `string_handler` will join the elements of the subset
    with the empty string (useful when `items` is an iterable of `str` variables).
    """
    ps = {0: [subset_handler()]}
    n = len(items)
    p_dict = partitions_by_length(n-1, sorting=True, permuting=True)
    for p_len, parts in p_dict.items():
        ps.setdefault(p_len, [])
        if p_len == 0:
            # singletons
            for offset in range(n):
                subset = subset_handler([items[offset]])
                if verbose:
                    if offset > 0:
                        print(end=" ")
                    if offset == n - 1:
                        print(subset, end="\n")
                    else:
                        print(subset, end=",")
                ps.get(p_len).append(subset)
        for pcount, partition in enumerate(parts):
            distance = sum(partition)
            indices = (cumsum(partition)).tolist()
            for offset in range(n - distance):
                subset = subset_handler([items[offset]] + [items[offset:][i] for i in indices])
                if verbose:
                    if offset > 0:
                        print(end=" ")
                    if offset == n - distance - 1:
                        print(subset, end="\n")
                    else:
                        print(subset, end=",")
                ps.get(p_len).append(subset)
        if verbose and p_len < n-1:
            print()
    return ps

作为示例,我编写了一个CLI演示程序,该程序将字符串作为命令行参数:

python string_powerset.py abcdef

a, b, c, d, e, f

ab, bc, cd, de, ef
ac, bd, ce, df
ad, be, cf
ae, bf
af

abc, bcd, cde, def
abd, bce, cdf
acd, bde, cef
abe, bcf
ade, bef
ace, bdf
abf
aef
acf
adf

abcd, bcde, cdef
abce, bcdf
abde, bcef
acde, bdef
abcf
abef
adef
abdf
acdf
acef

abcde, bcdef
abcdf
abcef
abdef
acdef

abcdef

答案 20 :(得分:0)

问题的一个变体是我在“发现计算机科学:跨学科问题,原理和Python编程。2015年版”一书中看到的一个练习。在练习10.2.11中,输入只是一个整数,而输出应为幂集。这是我的递归解决方案(除了基本的python3之外不使用其他任何东西)

def powerSetR(n):
    assert n >= 0
    if n == 0:
        return [[]]
    else:
        input_set = list(range(1, n+1)) # [1,2,...n]
        main_subset = [ ]
        for small_subset in powerSetR(n-1):
            main_subset += [small_subset]
            main_subset += [ [input_set[-1]] + small_subset]
        return main_subset

superset = powerSetR(4)
print(superset)       
print("Number of sublists:", len(superset))

输出为

[[],[4],[3],[4、3],[2],[4、2],[3、2],[4、3、2],[1],[ 4,1],[3,1],[4,3,1],[2,1],[4,2,1],[3,2,1],[4,3,2,1] ] 子列表数:16

答案 21 :(得分:0)

import math    
def printPowerSet(set,set_size): 
    pow_set_size =int(math.pow(2, set_size))
    for counter in range(pow_set_size):
    for j in range(set_size):  
        if((counter & (1 << j)) > 0):
            print(set[j], end = "")
    print("")
set = ['a', 'b', 'c']
printPowerSet(set,3)

答案 22 :(得分:0)

范围n中的所有子集均已设置:

n = int(input())
l = [i for i in range (1, n + 1)]

for number in range(2 ** n) :
    binary = bin(number)[: 1 : -1]
    subset = [l[i] for i in range(len(binary)) if binary[i] == "1"]
    print(set(sorted(subset)) if number > 0 else "{}")

答案 23 :(得分:0)

几乎所有这些答案都使用list而不是set,这对我来说似乎有点作弊。因此,出于好奇,我尝试在set上真正制作一个简单的版本,并为其他“ Python新手”进行总结。

我发现在处理Python的set implementation时有很多奇怪之处。给我的主要惊喜是处理空集。这与Ruby的Set implementation相反,我可以简单地做Set[Set[]]并得到一个包含一个空Set的{​​{1}},所以我最初发现它有点混乱。

回顾一下,在对Set进行powerset时,我遇到了两个问题:

  1. set进行迭代,因此set()将返回set(set()) because the empty set iterable is empty(我猜:))
  2. 要获取一组集合,set()set({set()})将不起作用,因为set.add(set) isn't hashable

为了解决这两个问题,我使用了set(),这意味着我并没有得到我想要的东西(类型从字面上是frozenset()),而是利用了整个{{1} }接口。

set

下面,我们正确地得到2²(16)set s作为输出:

def powerset(original_set):
  # below gives us a set with one empty set in it
  ps = set({frozenset()}) 
  for member in original_set:
    subset = set()
    for m in ps:
      # to be added into subset, needs to be
      # frozenset.union(set) so it's hashable
      subset.add(m.union(set([member]))
    ps = ps.union(subset)
  return ps

由于无法在Python中拥有frozensetIn [1]: powerset(set([1,2,3,4])) Out[2]: {frozenset(), frozenset({3, 4}), frozenset({2}), frozenset({1, 4}), frozenset({3}), frozenset({2, 3}), frozenset({2, 3, 4}), frozenset({1, 2}), frozenset({2, 4}), frozenset({1}), frozenset({1, 2, 4}), frozenset({1, 3}), frozenset({1, 2, 3}), frozenset({4}), frozenset({1, 3, 4}), frozenset({1, 2, 3, 4})} 中的set个,如果您想将这些set s转换为frozenset s个,则必须将它们映射回setlist)或进行修改。

答案 24 :(得分:0)

使用空集(它是所有子集的一部分),您可以使用:

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

答案 25 :(得分:0)

在Python 3.5或更高版本中,您可以将yield from语句与itertools.combinations一起使用:

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

答案 26 :(得分:0)

一种简单的方法是利用2的补码算法利用整数的内部表示。

整数的二进制表示形式为{000,001,010,011,100,101,110,111},范围从0到7。对于整数计数器值,将1视为集合中对应元素的包含,排除“ 0”,我们可以基于计数序列生成子集。必须从0pow(2,n) -1生成数字,其中n是数组的长度,即二进制表示形式的位数。

基于它的简单子集生成器功能可以编写如下。它基本上依赖

def subsets(array):
    if not array:
        return
    else:
        length = len(array)
        for max_int in range(0x1 << length):
            subset = []
            for i in range(length):
                if max_int & (0x1 << i):
                    subset.append(array[i])
            yield subset

然后可以用作

def get_subsets(array):
    powerset = []
    for i in subsets(array):
        powerser.append(i)
    return powerset

测试

在本地文件中添加关注

if __name__ == '__main__':
    sample = ['b',  'd',  'f']

    for i in range(len(sample)):
        print "Subsets for " , sample[i:], " are ", get_subsets(sample[i:])

给出以下输出

Subsets for  ['b', 'd', 'f']  are  [[], ['b'], ['d'], ['b', 'd'], ['f'], ['b', 'f'], ['d', 'f'], ['b', 'd', 'f']]
Subsets for  ['d', 'f']  are  [[], ['d'], ['f'], ['d', 'f']]
Subsets for  ['f']  are  [[], ['f']]

答案 27 :(得分:0)

以下是我使用组合但仅使用内置插件的快速实现。

def powerSet(array):
    length = str(len(array))
    formatter = '{:0' + length + 'b}'
    combinations = []
    for i in xrange(2**int(length)):
        combinations.append(formatter.format(i))
    sets = set()
    currentSet = []
    for combo in combinations:
        for i,val in enumerate(combo):
            if val=='1':
                currentSet.append(array[i])
        sets.add(tuple(sorted(currentSet)))
        currentSet = []
    return sets

答案 28 :(得分:0)

这很疯狂,因为这些答案实际上都没有提供实际Python集的返回。这是一个混乱的实现,它将提供一个实际上是Python set的powerset。

test_set = set(['yo', 'whatup', 'money'])
def powerset( base_set ):
    """ modified from pydoc's itertools recipe shown above"""
    from itertools import chain, combinations
    base_list = list( base_set )
    combo_list = [ combinations(base_list, r) for r in range(len(base_set)+1) ]

    powerset = set([])
    for ll in combo_list:
        list_of_frozensets = list( map( frozenset, map( list, ll ) ) ) 
        set_of_frozensets = set( list_of_frozensets )
        powerset = powerset.union( set_of_frozensets )

    return powerset

print powerset( test_set )
# >>> set([ frozenset(['money','whatup']), frozenset(['money','whatup','yo']), 
#        frozenset(['whatup']), frozenset(['whatup','yo']), frozenset(['yo']),
#        frozenset(['money','yo']), frozenset(['money']), frozenset([]) ])

我很乐意看到更好的实施。

答案 29 :(得分:-1)

def powerset(some_set):
    res = [(a,b) for a in some_set for b in some_set]
    return res