Python中的幂集操作

时间:2018-04-05 11:07:05

标签: python python-3.x list for-loop powerset

我正在操纵一个集合,所以如果你有一个n个独特元素的集合(又名:列表),那么你有2 ^ n个子集。在这里我将展示如何:

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]

l = list(powerset(["A", "B"]))
print(l) 

给出:

[[], ['A'], ['B'], ['A', 'B']]

现在如何使用上面的列表消除空列表,并合并最后一个元素,使其成为:

['A', 'B', 'AB']

我想重复此过程5次,获取最终输出并写入其子列表,消除空列表并合并它们属于同一子列表的那些元素。

5 个答案:

答案 0 :(得分:1)

首先,过滤掉falsy(空)元素,然后连接其余元素的元素:

>>> l = [[], ['A'], ['B'], ['A', 'B']]
>>> list(map(''.join, filter(bool, l)))
['A', 'B', 'AB']

等效列表 - 理解方式:

>>> l = [[], ['A'], ['B'], ['A', 'B']]
>>> [''.join(e) for e in l if e]
['A', 'B', 'AB']

这样做五次,做五次:

start = ["A", "B"]
for _ in range(5):
    start = [''.join(e) for e in powerset(start) if e]

答案 1 :(得分:1)

要摆脱空集,只需使用1代替0开始循环,然后''.join

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

如果你想重复这个,即获取原始列表的powerset的powerset,只需将结果反馈给循环中的函数:

lst = ["A", "B"]
for _ in range(5):
    lst = list(powerset(lst))
    print(lst)

话虽如此,将此过滤和加入作为后处理步骤更有意义,如@L3viathan的答案,因为真正的powerset函数既不应省略也不应修改结果

答案 2 :(得分:1)

data = [[], ['A'], ['B'], ['A', 'B']]
list(filter(None,map(lambda x:''.join(x) if x else None, data)))
>>>['A', 'B', 'AB']

答案 3 :(得分:0)

也许您需要flatmap之类的东西?

from itertools import chain, imap

def flatmap(f, items):
        return chain.from_iterable(imap(f, items))

>>> list(flatmap(lambda x: x, [[], ['A'], ['B'], ['A', 'B']]))
['A', 'B', 'A', 'B']

答案 4 :(得分:0)

这就是你要找的东西:

def powerset(s):
    x = len(s)
    masks = [1 << i for i in range(x)]
    for i in range(1 << x):
        item = ''.join([ss for mask, ss in zip(masks, s) if i & mask])
        if item:
            yield item
l = list(powerset(["A", "B", "C"]))
print(l) 
#['A', 'B', 'AB', 'C', 'AC', 'BC', 'ABC']

我介绍了C,因为它显然适用于AB