随机PHP数组,保证每个都有不同的密钥

时间:2014-08-06 21:47:20

标签: php shuffle

我正在建立礼品交换网站,人们在其中放入电子邮件,然后每个参赛者都与另一个参赛者(发件人)进行匹配。我使用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()实现我自己的糟糕版本,它可以将所有值向前移动两个,然后执行array_reverse()
  4. 循环收件人,并使用array_rand()$senders中选择一个项目。如果它相同,请再次选择,否则将其从阵列中删除,将其设置为该收件人的发件人,然后转到下一个收件人。
  5. 也许我过度思考这个问题 - 有更简单的方法吗?或者有一种特殊的方式在PHP中执行此操作,我不知道?

2 个答案:

答案 0 :(得分:5)

  1. 洗牌
  2. 制作副本
  3. 执行循环移位
  4. 结合

    $users = array('bob', 'alice', 'joe');
    
    shuffle($users);
    
    $santas = $users;
    $santas[] = array_shift($santas);
    
    $result = array_combine($santas, $users);
    
    var_dump($result);
    
  5. 演示:http://codepad.org/jxrzczRG

答案 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