如何获取集合的所有子集?(幂集)[重复]

2024-12-06 08:40:00
admin
原创
79
摘要:问题描述:给定一个集合{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},...

问题描述:

给定一个集合

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

解决方案 1:

Pythonitertools页面上有一个专门powerset用于此的菜谱:

from itertools import chain, combinations

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 长度的组合。

解决方案 2:

以下是幂集的更多代码。这是从头开始编写的:

>>> 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 的评论在这里适用:“如果你不喜欢开头的那个空元组,那么。”你可以将范围语句更改为 range(1, len(s)+1) 以避免 0 长度的组合”,除非在我的情况下你更改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意味着您不需要在一块内存中计算所有结果。在主循环之外预先计算掩码被认为是一种值得的优化。

解决方案 3:

如果你正在寻找一个快速的答案,我只需在谷歌上搜索“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]]

解决方案 4:

使用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)))

解决方案 5:

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

解决方案 6:

我发现以下算法非常清晰和简单:

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_powerset(remaining_list):
        subsets.append(partial_subset)
        subsets.append(partial_subset[:] + [first_element])

    return subsets

生成幂集的另一种方法是生成所有有n位的二进制数。作为幂集,有位数的数字数量n2 ^ n。该算法的原理是,元素可能存在于子集中,也可能不存在于子集中,因为二进制数字可以是 1 或 0,但不能同时为 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 计算思维和数据科学简介时发现了这两种算法,我认为这是我见过的最容易理解的算法之一。

解决方案 7:

对 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

解决方案 8:

TL;DR(直接进入简化)

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

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就是这样。我喜欢这个算法的原因是它比其他算法更清晰、更直观,因为即使它按预期工作,它看起来也很神奇。

解决方案 9:

这可以非常自然地完成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}

解决方案 10:

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 to it
      # effectively doubling the sets resulting in the 2^n sets in the powerset of s.
      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]]

解决方案 11:

我知道这太晚了

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

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

解决方案 12:

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

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 文档,还有有关幂集的维基百科条目

解决方案 13:

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

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

解决方案 14:

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

解决方案 15:

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 加倍

解决方案 16:

只需快速复习一下力量设置!

集合 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]))

全部归功于来源

解决方案 17:

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

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

解决方案 18:

你可以这样做:

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

解决方案 19:

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

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

基于此的简单子集生成器函数可以写成如下。它基本上依赖于

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

解决方案 20:

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

我发现在处理 Python 的集合实现时有几个奇怪的问题。最让我吃惊的是处理空集。这与 Ruby 的集合实现形成了鲜明对比,在 Ruby 中,我只需执行Set[Set[]]并获取一个Set包含一个空的集合Set,因此我最初觉得有点困惑。

回顾一下,在执行powersets时set,我遇到了两个问题:

  1. set()接受一个可迭代对象,因此set(set())将返回,set() 因为空集可迭代对象为空(我想是的:))

  2. 得到一组集合,set({set()})但因为不可哈希而set.add(set)不起作用set()

为了解决这两个问题,我使用了frozenset(),这意味着我没有完全得到我想要的(类型是字面意思set),但利用了整体set界面。

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

下面我们frozenset正确地得到了 2² (16) 作为输出:

In [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})}

由于 Python 中没有办法拥有sets set,如果您想将这些frozensets 变成sets ,您必须将它们映射回list( list(map(set, powerset(set([1,2,3,4]))))) 或修改上述内容。

解决方案 21:

也许这个问题已经过时了,但我希望我的代码能够对某些人有所帮助。

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

解决方案 22:

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

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

解决方案 23:

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

解决方案 24:

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

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

不过,我希望看到更好的实现。

解决方案 25:

这是我利用组合但仅使用内置函数的快速实现。

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

解决方案 26:

范围 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 "{}")

解决方案 27:

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)

解决方案 28:

这个问题的一个变体是我在《发现计算机科学:跨学科问题、原则和 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

解决方案 29:

我没有遇到过该more_itertools.powerset函数,建议使用它。我还建议不要使用输出的默认顺序itertools.combinations,通常你希望最小化位置之间的距离,并将距离较短的项目子集排序在距离较大的项目的上方/之前。

itertools食谱页面显示它使用chain.from_iterable

  • 请注意,这里的 与二项式系数r下部的标准符号相匹配,在数学文本和计算器中通常称为(“n 选择 r”)s`n`

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

此处的其他示例[1,2,3,4]以这样一种方式给出了 的幂集,即 2 元组按“字典顺序”列出(当我们将数字打印为整数时)。如果我在旁边写上数字之间的距离(即差值),它就表明了我的观点:

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

对于更多的项目来说,这种影响更加明显,并且对于我的目的而言,它使得能够有意义地描述幂集索引的范围变得不同。

(关于组合算法的输出顺序,有大量关于格雷码等方面的论述,我不认为这是一个次要问题)。

实际上,我刚刚编写了一个相当复杂的程序,它使用这个快速整数分区代码以正确的顺序输出值,但后来我发现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)

我编写了一些更复杂的代码,可以很好地打印幂集(请参阅 repo 中我没有包含的漂亮打印功能:print_partitions,,print_partitions_by_lengthpprint_tuple)。

  • 回购:ordered-powerset,具体来说pset_partitions.py

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

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="
")
                    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="
")
                    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

解决方案 30:

这是我的解决方案,它(概念上)与 lmiguelvargasf 的解决方案类似。

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

因此输入是一个列表,输出将是一个列表的列表。该函数可以提前关闭,但我喜欢幂集的元素按字典顺序排列,这本质上意味着很好。

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
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   990  
  在项目管理领域,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节,它不仅验证了项目团队的专业能力,还直接关系到项目的成功与否。在这一评审过程中,沟通技巧的运用至关重要。有效的沟通不仅能够确保信息的准确传递,还能增强团队协作,提升评审效率。本文将深入探讨CDCP...
华为IPD流程   26  
  IPD(Integrated Product Development,集成产品开发)是一种以客户需求为核心、跨部门协同的产品开发模式,旨在通过高效的资源整合和流程优化,提升产品开发的成功率和市场竞争力。在IPD培训课程中,掌握关键成功因素是确保团队能够有效实施这一模式的核心。以下将从五个关键成功因素展开讨论,帮助企业和...
IPD项目流程图   27  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司在其全球化进程中逐步构建和完善的一套高效产品开发管理体系。这一流程不仅帮助华为在技术创新和产品交付上实现了质的飞跃,还为其在全球市场中赢得了显著的竞争优势。IPD的核心在于通过跨部门协作、阶段性评审和市场需求驱动,确保...
华为IPD   26  
  华为作为全球领先的通信技术解决方案提供商,其成功的背后离不开一套成熟的管理体系——集成产品开发(IPD)。IPD不仅是一种产品开发流程,更是一种系统化的管理思想,它通过跨职能团队的协作、阶段评审机制和市场需求驱动的开发模式,帮助华为在全球市场中脱颖而出。从最初的国内市场到如今的全球化布局,华为的IPD体系在多个领域展现...
IPD管理流程   53  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用