这是一个相当幼稚的实现:
from itertools import combinations
from typing import Set, List, Generator
def generate_sessions(people: Set, excl: List[Set]) -> Generator[List[Set], None, None]:
# all the pairings you need are all possible pairings, except the exclusions
needed_pairings = [set(pair) for pair in combinations(people, 2)]
for pair in excl:
needed_pairings.remove(pair)
# while there pairing that haven't happened yet
while needed_pairings:
# each session starts empty
session = []
# keep track of all people still available for this session
available = set(people)
# create an iterator, so we can loop over the needed pairings
iter_needed_pairings = iter(needed_pairings)
# as long as there are more than 2 people still waiting and there's a pair left in the needed pairings
while (len(available) > 1) and (pair := next(iter_needed_pairings, False)):
# are both people in the pair in the group of available people?
if available.intersection(pair) == pair:
# then they can meet in this session
session.append(pair)
# and they're no longer available
available -= pair
# once we have a session, remove the pairs in it from the pairings still needed
for pair in session:
needed_pairings.remove(pair)
# yield the session
yield session
print(list(generate_sessions(people={'John', 'Steve', 'Mark', 'Melissa'}, excl=[{'John', 'Melissa'}])))
结果(可能会因集合的无序性质而有所不同):
[[{'John', 'Mark'}, {'Melissa', 'Steve'}], [{'John', 'Steve'}, {'Melissa', 'Mark'}], [{'Mark', 'Steve'}]]
这会生成会话,直到每个人都见面为止。您可以从生成器中获取next(),直到您有足够的会话。这种方法的唯一缺点是它可能会在一个有更多人开会的会话之前找到几个人正在等待的会话。您可以通过按长度对会话进行排序来解决这个问题,但这当然意味着生成所有会话。
编辑:我添加了输入信息,以明确预期的类型是什么,但它当然不需要它来工作。