在Python中生成大小为k(包含k个元素)的所有子集

时间:2011-09-11 12:31:00

标签: python set tuples subset

我有一组值,想要创建包含2个元素的所有子集的列表。

例如,源集([1,2,3])具有以下2元素子集:

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

有没有办法在python中执行此操作?

3 个答案:

答案 0 :(得分:27)

好像你想要itertools.combinations

>>> list(itertools.combinations((1, 2, 3), 2))
[(1, 2), (1, 3), (2, 3)]

如果你想要套装,你必须明确地转换它们。如果您不介意迭代而不是列表,并且您使用的是Python 3,则可以使用map

>>> s = set((1, 2, 3))
>>> map(set, itertools.combinations(s, 2))
<map object at 0x10cdc26d8>

要一次查看所有结果,您可以将map的输出传递给list。 (在Python 2中,map的输出自动为列表。)

>>> list(map(set, itertools.combinations(s, 2)))
[{1, 2}, {1, 3}, {2, 3}]

但是,如果你知道你需要一个列表,那么列表理解会稍微好一些(h / t Jacob Bowyer):

>>> [set(i) for i in itertools.combinations(s, 2)]
[{1, 2}, {1, 3}, {2, 3}]

答案 1 :(得分:2)

这是包含所有双元素集的{1, 2, 3}(或任何集合)的power set的子集。

请参阅Python itertools documentation并搜索术语“powerset”以获取此问题的一般答案。

答案 2 :(得分:1)

为了给出另一个观点,我找到了一种方法来迭代{1.....N}的所有2的子集,所以我将itertools.combinations置于测试中:

import itertools
from time import time


N = 7000
lst = [i for i in xrange(N)]

st = time()
c1 = 0
for x in itertools.combinations(lst, 2):
    c1 += 1
print "combinations: %f" % (time()-st)

st = time()
c2=0
for x in xrange(N):
    for y in xrange(x):
        c2 += 1
print "double loop: %f" % (time()-st)
print "c1=%d,c2=%d" % (c1,c2)

# prints:
#combinations: 4.247000
#double loop: 3.479000
# c1=24496500,c2=24496500

所以我猜你不应该总是变成一般的解决方案....如果你事先知道你想要的子集的大小,那么使用for循环迭代应该更有效。

另请注意,您不应迭代list(itertools.combinations(lst, 2)),因为此移动会创建列表(并且比使用生成器本身要慢得多)。