Shuffle PHP数组,确保每个都有不同的键

问题描述 投票:0回答:2

我正在建立一个礼物交换网站,人们在其中输入电子邮件,然后每个参赛者都与另一个参赛者(发送者)匹配。我正在使用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']

因此,我需要保证在最终数组中,没有任何值等于键。到目前为止,我已经想到了以下可能的解决方案,但它们似乎都很昂贵且有点垃圾:

  1. 在最终数组上使用array_walk()。将任何值放入另一个数组,然后相互交换。如果只有1,则将其交换任何内容。
  2. [取$recipients数组中所有具有偶数键的值,以及$senders数组中所有具有奇数键的值。随机排列这两个数组。
  3. 而不是使用shuffle()实现我自己的cr脚版本,该版本执行的操作类似于将所有值前移两个,然后执行array_reverse()
  4. 循环浏览收件人,然后使用array_rand()$senders中选择一项。如果相同,请再次选择,否则将其从阵列中删除,将其设置为该收件人的发件人,然后移至下一个收件人。

也许我对此考虑过多-有没有更简单的方法?还是有一种我不知道的在PHP中执行此操作的特殊方法?

php shuffle
2个回答
5
投票
  1. 随机播放
  2. 创建副本
  3. 执行循环移位
  4. combine

    $users = array('bob', 'alice', 'joe');
    
    shuffle($users);
    
    $santas = $users;
    $santas[] = array_shift($santas);
    
    $result = array_combine($santas, $users);
    
    var_dump($result);
    

演示:http://codepad.org/jxrzczRG


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

© www.soinside.com 2019 - 2024. All rights reserved.