我正在建立礼品交换网站,人们在其中放入电子邮件,然后每个参赛者都与另一个参赛者(发件人)进行匹配。我使用PHP(可能是Symfony,如果它有所作为)。
我预计参赛人数大约在600-800之间,并且会经常运行。
我以为我可以在收件人数组上使用shuffle()
和array_combine()
来执行此操作。
但是,在shuffle()
发件人仍然处于相同位置之后,所以必须向他们自己提供秘密圣诞老人。
例如:
$recipients = "SQL query that returns array"
# ['bob', 'alice', 'joe']
$senders = $recipients;
shuffle($senders);
# ['alice', 'bob', 'joe']
$result = array_combine($recipients, $senders);
# ['bob' => 'alice', 'alice' = 'bob', 'joe' => 'joe']
所以我需要保证在最后一个数组中,没有一个值等于键。到目前为止,我已经想到了以下可能的解决方案,但它们看起来都很昂贵而且有点垃圾:
array_walk()
。将任何值放入另一个数组中,然后将它们相互交换。如果只有1,只需将其与任何东西交换。$recipients
数组获取具有偶数键的所有值,以及具有奇数键的$senders
数组中的所有值。洗牌这两个阵列。shuffle()
实现我自己的糟糕版本,它可以将所有值向前移动两个,然后执行array_reverse()
。array_rand()
从$senders
中选择一个项目。如果它相同,请再次选择,否则将其从阵列中删除,将其设置为该收件人的发件人,然后转到下一个收件人。也许我过度思考这个问题 - 有更简单的方法吗?或者有一种特殊的方式在PHP中执行此操作,我不知道?
答案 0 :(得分:5)
结合
$users = array('bob', 'alice', 'joe');
shuffle($users);
$santas = $users;
$santas[] = array_shift($santas);
$result = array_combine($santas, $users);
var_dump($result);
答案 1 :(得分:0)
您还可以使用与Fisher-Yates shuffle类似的代码。
function santaYates($array) {
$keys = array_keys($array); //Store the keys
$values = array_values($array); // Cause we need a clean numeric array for this kind of randomisation
$secure = false;
for($i = count($values) - 1; $i > 0; $i--) {
$r = mt_rand(0, $i-1); //subtract 1 from $i to force a new place.
$tmp = $values[$i];
$values[$i] = $values[$r];
$values[$r] = $tmp;
}
$returnArray = array_combine($keys, $values); //Now recombine keys and values
return $returnArray;
}
我为answering a similar question编写了此代码,但是该版本也可以处理关联数组。 您可以Test this version