生成列表的所有可能组合,“itertools.combinations”会遗漏一些结果
Posted
技术标签:
【中文标题】生成列表的所有可能组合,“itertools.combinations”会遗漏一些结果【英文标题】:Generating all possible combinations of a list, "itertools.combinations" misses some results 【发布时间】:2013-06-30 07:42:45 【问题描述】:给定 Python 中的项目列表,我如何获得项目的所有可能组合?
这个网站上有几个类似的问题,建议使用itertools.combinations
,但只返回我需要的子集:
stuff = [1, 2, 3]
for L in range(0, len(stuff)+1):
for subset in itertools.combinations(stuff, L):
print(subset)
()
(1,)
(2,)
(3,)
(1, 2)
(1, 3)
(2, 3)
(1, 2, 3)
如您所见,它仅返回严格顺序的项目,不返回 (2, 1)
、(3, 2)
、(3, 1)
、(2, 1, 3)
、(3, 1, 2)
、(2, 3, 1)
和 (3, 2, 1)
。有什么解决方法吗?我好像什么都想不出来。
【问题讨论】:
组合中的顺序无所谓,(2, 1) 和(1, 2)一样 好问题。虽然从技术上讲,您可以编写自己的函数来获得这些组合。 【参考方案1】:使用itertools.permutations
:
>>> import itertools
>>> stuff = [1, 2, 3]
>>> for L in range(0, len(stuff)+1):
for subset in itertools.permutations(stuff, L):
print(subset)
...
()
(1,)
(2,)
(3,)
(1, 2)
(1, 3)
(2, 1)
(2, 3)
(3, 1)
....
求助itertools.permutations
:
permutations(iterable[, r]) --> permutations object
Return successive r-length permutations of elements in the iterable.
permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)
【讨论】:
【参考方案2】:您可以使用这个简单的代码在python中生成列表的所有组合
import itertools
a = [1,2,3,4]
for i in xrange(1,len(a)+1):
print list(itertools.combinations(a,i))
结果:
[(1,), (2,), (3,), (4,)]
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
[(1, 2, 3, 4)]
【讨论】:
要求在结果中查看 (2, 1) 的问题。您的答案中的 (2, 1) 在哪里? 组合 (2, 1) 和 (1, 2) 都是同一个家伙。 尽管问题中有“组合”,但它的意思是排列。读到最后,发现 (2, 1) 和 (1, 2) 都是 OP 所期望的。【参考方案3】:您是在寻找itertools.permutations
吗?
来自help(itertools.permutations)
,
Help on class permutations in module itertools:
class permutations(__builtin__.object)
| permutations(iterable[, r]) --> permutations object
|
| Return successive r-length permutations of elements in the iterable.
|
| permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)
示例代码:
>>> from itertools import permutations
>>> stuff = [1, 2, 3]
>>> for i in range(0, len(stuff)+1):
for subset in permutations(stuff, i):
print(subset)
()
(1,)
(2,)
(3,)
(1, 2)
(1, 3)
(2, 1)
(2, 3)
(3, 1)
(3, 2)
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)
来自***,排列组合的区别:
排列:
非正式地,一组对象的排列是这些对象按特定顺序排列。例如,集合1,2,3有六个排列,分别是(1,2,3), (1,3,2), (2,1,3), (2,3,1) , (3,1,2) 和 (3,2,1)。
组合:
在数学中,组合是从一个更大的组中选择多个事物的一种方式,其中(与排列不同)顺序无关紧要。
【讨论】:
【参考方案4】:itertools.permutations
将是您想要的。根据数学定义,combinations
的顺序无关紧要,这意味着(1,2)
被认为与(2,1)
相同。而对于permutations
,每个不同的排序都算作一个唯一的排列,所以(1,2)
和(2,1)
是完全不同的。
【讨论】:
【参考方案5】:这里是没有 itertools 的解决方案
首先让我们定义0
和1
s的指示向量与子列表(1
如果项目在子列表中)之间的转换
def indicators2sublist(indicators,arr):
return [item for item,indicator in zip(arr,indicators) if int(indicator)==1]
接下来,定义一个从0
和2^n-1
之间的数字到其二进制向量表示的映射(使用字符串的format
函数):
def bin(n,sz):
return ('d:0'+str(sz)+'b').format(d=n)
我们剩下要做的就是迭代所有可能的数字,然后调用indicators2sublist
def all_sublists(arr):
sz=len(arr)
for n in xrange(0,2**sz):
b=bin(n,sz)
yield indicators2sublist(b,arr)
【讨论】:
【参考方案6】:我假设您希望所有可能的组合都作为值的“集合”。这是我编写的一段代码,可能有助于您了解一下:
def getAllCombinations(object_list):
uniq_objs = set(object_list)
combinations = []
for obj in uniq_objs:
for i in range(0,len(combinations)):
combinations.append(combinations[i].union([obj]))
combinations.append(set([obj]))
return combinations
这是一个示例:
combinations = getAllCombinations([20,10,30])
combinations.sort(key = lambda s: len(s))
print combinations
... [set([10]), set([20]), set([30]), set([10, 20]), set([10, 30]), set([20, 30]), set([10, 20, 30])]
我认为这有 n!时间复杂度,所以要小心。这可行,但可能不是最有效的
【讨论】:
【参考方案7】:我只是想把它放在那里,因为我无法对每一个可能的结果都进行优化,并且请记住,当涉及到 python 时,我只有最原始的最基本知识,并且可能有一个更优雅的解决方案...... (也请原谅可怜的变量名
测试 = [1, 2, 3]
测试2= [0]
n = -1
def testingSomethingElse(number):
try:
testing2[0:len(testing2)] == testing[0]
n = -1
testing2[number] += 1
except IndexError:
testing2.append(testing[0])
当真时:
n += 1
testing2[0] = testing[n]
print(testing2)
if testing2[0] == testing[-1]:
try:
n = -1
testing2[1] += 1
except IndexError:
testing2.append(testing[0])
for i in range(len(testing2)):
if testing2[i] == 4:
testingSomethingElse(i+1)
testing2[i] = testing[0]
我逃脱了 == 4 因为我正在使用整数,但您可能需要相应地修改它...
【讨论】:
以上是关于生成列表的所有可能组合,“itertools.combinations”会遗漏一些结果的主要内容,如果未能解决你的问题,请参考以下文章