【问题标题】:Generate all subsets of size k (containing k elements) in Python在 Python 中生成所有大小为 k(包含 k 个元素)的子集
【发布时间】:2011-11-14 17:52:06
【问题描述】:

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

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

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

有没有办法在 python 中做到这一点?

【问题讨论】:

    标签: python set tuples subset


    【解决方案1】:

    好像你想要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}]
    

    【讨论】:

    • 该死!顺便说一句,你的地图可以用列表 comp [set(i) for i in itertools.combinations(s, 2))]
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      只是为了提供另一个视角,我寻找一种方法来迭代{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)),因为此操作会创建列表(并且比使用生成器本身要慢得多)。

      【讨论】:

      • 这两个测试不做同样的事情。 itertools.combinations 实际上创建了一个元组;您的嵌套循环不会创建元组。
      • 我做了一个快速测试。如果你真的需要在嵌套循环中创建元组,它会慢 50%。此外,如果您不需要使用for 循环来处理itertools.combinations 的输出,则可以使用此生成器表达式获得显着的加速:c3 = sum(1 for pair in itertools.combinations(lst, 2))。这比最快的嵌套循环快 40%。在优化此类代码时,总是需要考虑许多细微之处!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      • 2011-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多