从列表中形成随机对(某种...) [英] forming random pairs from a list (sort of...)

查看:89
本文介绍了从列表中形成随机对(某种...)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

跳至上一次修改

我有一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆