我有一个包含 50 个数字的列表,[0,1,2,...49] 我想创建一个没有重复的元组列表,我在其中定义 ( a,b) 是 (b,a) 的副本。同样,我不想要 (a,a) 形式的元组。
我有这个:
pairs = set([])
mylist = range(0,50)
for i in mylist:
for j in mylist:
pairs.update([(i,j)])
set((a,b) if a<=b else (b,a) for a,b in pairs)
print len(pairs)
>>> 2500
我得到了 2500,而我希望得到 1225 (n(n-1)/2)。
怎么了?
请您参考如下方法:
您想要所有组合。 Python 提供了一个模块,itertools,其中包含诸如此类的各种组合实用程序。在可能的情况下,我会坚持使用 itertool,它几乎肯定比您自己编写的任何东西都更快,内存效率更高。它也经过了实战考验。你不应该重新发明轮子。
>>> import itertools
>>> combs = list(itertools.combinations(range(50),2))
>>> len(combs)
1225
>>>
然而,正如其他人所指出的,如果您有一个序列(即可索引的东西),例如列表,并且您希望 N 选择 k,其中 k=2,则上述内容可以简单地通过嵌套 for-遍历索引,注意智能地生成索引:
>>> result = []
>>> for i in range(len(numbers)):
... for j in range(i + 1, len(numbers)):
... result.append((numbers[i], numbers[j]))
...
>>> len(result)
1225
但是,itertool.combinations 采用任何可迭代,并且还采用第二个参数 r,它处理 k 可以是某物的情况像 7,(你不想写楼梯)。
您的方法本质上采用笛卡尔积,然后进行过滤。这是低效的,但如果你想这样做,最好的方法是使用 frozensets:
>>> combinations = set()
>>> for i in numbers:
... for j in numbers:
... if i != j:
... combinations.add(frozenset([i,j]))
...
>>> len(combinations)
1225
还有一个使事物成为元组的过程:
>>> combinations = [tuple(fz) for fz in combinations]
