3 回答
TA贡献1784条经验 获得超7个赞
from itertools import cycle , islice, chain
def round_robin(iterable):
items = list(iterable)
if len(items) % 2 != 0:
items.append(None)
fixed = items[:1]
cyclers = cycle(items[1:])
rounds = len(items) - 1
npairs = len(items) // 2
return [
list(zip(
chain(fixed, islice(cyclers, npairs-1)),
reversed(list(islice(cyclers, npairs)))
))
for _ in range(rounds)
for _ in [next(cyclers)]
]
TA贡献1966条经验 获得超4个赞
我只生成索引(因为我很难输入1000个名称=),但是对于1000个数字,运行时间约为4秒。
所有其他方法的主要问题-它们使用成对并与它们一起工作,成对存在很多,并且运行时间越来越长。我的方法与人合作而不是与他人合作有所不同。我有一个dict()将人映射到他必须遇到的其他人的列表的列表,这些列表的长度最多为N个项目(不是N ^ 2,与配对一样)。因此节省了时间。
#!/usr/bin/env python
from itertools import combinations
from collections import defaultdict
pairs = combinations( range(6), 2 )
pdict = defaultdict(list)
for p in pairs :
pdict[p[0]].append( p[1] )
while len(pdict) :
busy = set()
print '-----'
for p0 in pdict :
if p0 in busy : continue
for p1 in pdict[p0] :
if p1 in busy : continue
pdict[p0].remove( p1 )
busy.add(p0)
busy.add(p1)
print (p0, p1)
break
# remove empty entries
pdict = { k : v for k,v in pdict.items() if len(v) > 0 }
'''
output:
-----
(0, 1)
(2, 3)
(4, 5)
-----
(0, 2)
(1, 3)
-----
(0, 3)
(1, 2)
-----
(0, 4)
(1, 5)
-----
(0, 5)
(1, 4)
-----
(2, 4)
(3, 5)
-----
(2, 5)
(3, 4)
'''
TA贡献1828条经验 获得超13个赞
您可以立即做两件事:
不要每次都通过列表复制该集合。那是浪费大量的时间/内存。而是在每次迭代后修改一次集。
在每个回合中保留一组单独的人。在一个集合中查找一个人比在整个回合中循环要快一个数量级。
前任:
def make_rounds(people):
people_pairs = set(combinations(people, 2))
while people_pairs:
round = set()
people_covered = set()
for pair in people_pairs:
if pair[0] not in people_covered \
and pair[1] not in people_covered:
round.add(pair)
people_covered.update(pair)
people_pairs -= round # remove thi
yield round
比较:
添加回答
举报