【问题标题】:Combination of 1 and 0 in an array in PythonPython中数组中1和0的组合
【发布时间】:2014-07-07 11:50:17
【问题描述】:

我想在二维数组中组合 1 和 0,如下所示:

[[ 1, 1, 1, 1, 0, 0, 0, 0 ],
 [ 1, 1, 1, 0, 1, 0, 0, 0 ],
 [ 1, 1, 1, 0, 0, 1, 0, 0 ],
 [ 1, 1, 1, 0, 0, 0, 1, 0 ],
 [ 1, 1, 1, 0, 0, 0, 0, 1 ],
 .
 .
 .
]

这意味着四个 1 和四个 0 的组合。我查看了itertools 模块的permutations() 和combinations(),但找不到任何合适的函数来执行这种组合。

【问题讨论】:

标签: python python-2.7 combinations itertools


【解决方案1】:

您也可以使用combinations直接生成唯一组合:

n = 8
n1 = 4
for x in itertools.combinations( xrange(n), n1 ) :
    print [ 1 if i in x else 0 for i in xrange(n) ] 

[1, 1, 1, 1, 0, 0, 0, 0]
[1, 1, 1, 0, 1, 0, 0, 0]
[1, 1, 1, 0, 0, 1, 0, 0]
[1, 1, 1, 0, 0, 0, 1, 0]
...
[0, 0, 0, 1, 1, 1, 0, 1]
[0, 0, 0, 1, 1, 0, 1, 1]
[0, 0, 0, 1, 0, 1, 1, 1]
[0, 0, 0, 0, 1, 1, 1, 1]

这比permutations 更有效,因为您不会重复不需要的解决方案。

直觉是,您正在尝试找到所有可能的方法来将四个“1”放入长度为 8 的序列中;这就是combinations 的确切定义。该号码是C(8,4)=8! / (4! * 4!) = 70。相比之下,使用permutations 的解决方案会迭代8! = 40,320 候选解决方案。

【讨论】:

  • +1 但是,我仍然更喜欢permutations 解决方案,尤其是单线,因为它立即清楚代码的作用,并且生成开销也不是那么大(但可能需要更多位)。
  • 这就是我想要的。非常感谢我。
  • @tobias_k:使用permutations 的解决方案可能更具可读性,但请尝试将其与n>15 一起使用...
  • 啊,找到了这个词:multiset permutation。
  • @usualme 是的,这基本上就是我想在评论中表达的内容。 ;-)
【解决方案2】:

您正在生成permutation of a multiset。

简单但幼稚的方法是使用itertools.permutations(),用一个集合来过滤掉重复的组合:

>>> from itertools import permutations
>>> seen = set()
>>> for combo in permutations([1] * 4 + [0] * 4):
...     if combo not in seen:
...         seen.add(combo)
...         print combo
...
(1, 1, 1, 1, 0, 0, 0, 0)
(1, 1, 1, 0, 1, 0, 0, 0)
(1, 1, 1, 0, 0, 1, 0, 0)
(1, 1, 1, 0, 0, 0, 1, 0)
(1, 1, 1, 0, 0, 0, 0, 1)
(1, 1, 0, 1, 1, 0, 0, 0)
# ...
(0, 0, 1, 0, 1, 0, 1, 1)
(0, 0, 1, 0, 0, 1, 1, 1)
(0, 0, 0, 1, 1, 1, 1, 0)
(0, 0, 0, 1, 1, 1, 0, 1)
(0, 0, 0, 1, 1, 0, 1, 1)
(0, 0, 0, 1, 0, 1, 1, 1)
(0, 0, 0, 0, 1, 1, 1, 1)

或者,一次性生成整个序列:

set(permutations([1] * 4 + [0] * 4))

但这会丢失permutations 产生的顺序。

需要该集合,因为 permutations() 将 4 个 1 和 4 个 0 视为单独的字符,一个 1 与另一个交换被认为是唯一的排列。

您还可以使用序列中的排序来避免使用集合:

last = (1,) * 8
for combo in permutations([1] * 4 + [0] * 4):
    if combo < last:
        last = combo
        print combo

这种方法在那个 2n 中是幼稚的!在我们只想要(2n 选择 n)个元素的地方产生排列。对于您的情况,这是 40320 个排列,我们只需要产生 70 个。

【讨论】:

  • 或者只是set(itertools.permutations([1]*4+[0]*4))?
  • @tobias_k:是的,但是你不得不一口气制作出整套产品,而且顺序可能很重要。
  • 由于集合只有 70 个元素,我认为这不是什么大问题,也不是像 sorted(set(...), reverse=True) 那样对集合进行排序。 +1
  • 感谢 tobias_k。它完成了。但是,正如我给出的问题一样,我怎样才能像矩阵一样制定它。喜欢[[],[],[]]格式
  • @user3812253: permutations() 产生元组;您可以轻松地在每个尚未看到的结果上调用 list() 并将其添加到列表中。
猜你喜欢
  • 1970-01-01
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多