从列表中形成随机对(某种...) [英] forming random pairs from a list (sort of...)
问题描述
跳至上一次修改
我有一个Person
对象的列表,我需要使用randomize_pairs
函数将它们随机配对,每个Person
对象都有一个与谁配对的属性target
.
I have a list of Person
objects and I need to pair them off randomly with a randomize_pairs
function, each Person
object has a property target
of who they are paired with.
我的约束是,没有人可以与自己配对(duh),不应将他们与同一个人配对两次.
My constraints are that no-one can pair with themselves (duh) and they shouldn't be paired with the same person twice.
我通过制作一个临时列表并在满足约束条件的情况下将人赶出了工作,但是我敢肯定,这样做有一种更干净/更好/更精妙的方法.有人知道吗?
I got this working by making a temporary list and popping people off if the constraints were satisfied but I'm sure there is a cleaner/better/more pythonic way of doing this. Anyone know?
在这个问题中我经常使用"pair"一词,但这是错误的词.这是针对将每个人都分配给另一个人作为目标的游戏,因此这是一种关系,其中目标的目标不一定是您.
I used the word "pair" a lot in this question but that was the wrong word. This is for a game where each person is assigned another person as a target so these are one way relationships where your target's target is not necessarily you.
目标只会在每个回合开始时更改,因此只需一次即可.
Targets will only be changed at the beginning of each round so it's all at once.
这是我现在所要解决的问题尽管可以改进,所以我将问题悬而未决.
Here's what I've settled on for now though it can be improved so I'm leaving the question open.
def randomize_targets(players):
# get player count
count = len(players)
# copy the list of players
available_targets = list(players)
# shuffle the player order so if the last one has to have the same
# target twice it's not always the same player
players = list(players)
random.shuffle(players)
# loop over each player
for player in players:
# get the list of possible targets
potential_targets = [target for target in available_targets \
if target != player \
and target != player.target]
# try to pick one at random
try:
target = random.choice(potential_targets)
# if we have to, use the same target as last time
except IndexError:
pass
# remove the target from the available targets list
available_targets.remove(target)
# assign target
player.target = target
编辑3
我决定使用这种方法,尽管我不喜欢可能很长的循环时间,直到找到一个至少可以正常工作的组合为止
edit 3
I decided on this method even though I don't like the potentially long time looping until it finds a combo that works at least it always yields valid results
def randomize_targets2 (players):
targets = list(players)
# run this until it generates a valid result
valid = False
while not valid:
# randomize the targets
random.shuffle(targets)
# validate them
round_valid = True
for player, target in zip(players, targets):
round_valid = round_valid and player != target and player.target != target
valid = round_valid
# apply the validated targets
for player, target in zip(players, targets):
player.target = target
推荐答案
我假设由于您希望随机选择人员,因此列表的选择可提供快速的随机访问.一个简单的解决方案是随机整理整个列表,然后将人们从列表的前面成对配对.
I assume that since you want to select people at random, your choice of list provides fast random access. A simple solution is just to shuffle the whole list, and just pair people off in pairs from the front of the list.
Fisher-Yates随机播放 ,是一种随机排列列表的简便方法.
The Fisher-Yates shuffle is a quick, easy way to shuffle the list randomly.
然后,您可以运行并配对:
Then you can just run through and pair them off:
for x from 0 to persons.size(), x += 2
pair(persons.get(i), persons.get(i + 1));
由于元素是独特的,因此您不必担心人们会两次配对或与自己配对.
Since the elements are unique, you won't have to worry about people getting paired twice or with themselves.
还要小心,首先确保列表中的人数是偶数!如果总数很奇怪,您将不得不以某种方式与名单末尾的那个额外的人打交道.
Also be careful to make sure your list has an even number of people first! If the total is odd you'll have to deal with the extra person at the end of the list somehow.
这篇关于从列表中形成随机对(某种...)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!