我有一个包含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)。
有什么问题?
答案 0 :(得分:9)
您想要所有组合。 Python提供了一个模块itertools
,其中包含各种类似的组合实用程序。在可以的地方,我会坚持使用itertool
,它几乎肯定比你自己做的任何事情都更快,更有效。它也经过了战斗考验。你不应该重新发明轮子。
>>> import itertools
>>> combs = list(itertools.combinations(range(50),2))
>>> len(combs)
1225
>>>
然而,正如其他人所指出的那样,如果你有一个序列(即可索引的东西),例如列表,你想要N选择k,其中k = 2,上面的内容可以简单地通过嵌套实现 - 循环索引,注意智能地生成索引:
>>> 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]
答案 1 :(得分:2)
试试这个,
pairs = set([])
mylist = range(0,50)
for i in mylist:
for j in mylist:
if (i < j):
pairs.append([(i,j)])
print len(pairs)
答案 2 :(得分:2)
问题是您过滤掉了不需要的值,但是您没有将分配回pairs
,所以长度是相同的......也是:此公式产生了结果错误,因为它将(20,20)
视为有效。
但您应该立即创建正确的列表:
pairs = set()
for i in range(0,50):
for j in range(i+1,50):
pairs.add((i,j))
print (len(pairs))
结果:
1225
使用该方法您甚至不需要set
,因为它保证您首先没有重复项:
pairs = []
for i in range(0,50):
for j in range(i+1,50):
pairs.append((i,j))
或使用列表理解:
pairs = [(i,j) for i in range(0,50) for j in range(i+1,50)]