【问题标题】:Shuffle PHP array, guaranteeing each has a different key随机播放 PHP 数组,保证每个数组都有不同的键
【发布时间】:2014-08-06 21:47:20
【问题描述】:

我正在建立一个礼品交换网站,人们在其中输入他们的电子邮件,然后每个参赛者与另一个参赛者(发件人)匹配。我正在使用 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 中选择一个项目。如果相同,请再次选择,否则将其从数组中删除,将其设置为该收件人的发件人,然后转到下一个收件人。

也许我想多了 - 有没有更简单的方法?或者有没有我不知道的 PHP 中的特殊方法?

【问题讨论】:

标签: php shuffle


【解决方案1】:
  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);
    

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

【讨论】:

  • 循环移位是什么意思?
  • @Blowski 将您的数组想象成一个滚动磁盘,因此当您将数组向前移动一个位置时,最后一个元素占据第一个位置,第一个元素占据第二个位置,依此类推。
  • 哦,刚刚看了,我想我明白了。 shuffle()数组,然后做一个简单版的解决方案#3
  • @zerkms 一直在考虑这个问题,但仍然不能保证在结果数组中,没有用户会等于相关的圣诞老人。它们可以在循环移位之前处于不同的位置,然后在循环移位之后处于相同的位置。
  • @Blowski:这是有保证的。只要总数超过 2 人 - 在循环轮班之后,他们将总是不同。如果你仍然认为我错了 - 尝试提供 shuffled $users 数组来证明你的观点。
【解决方案2】:

您也可以使用与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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-16
    • 2023-03-18
    • 2014-04-21
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    • 2020-12-10
    相关资源
    最近更新 更多