PHP Zend实现Secret Santa脚本奇数用户数出现重复条目的问题
问题成因
核心问题出在递归逻辑的执行流程设计缺陷:
- PHP数组为值传递,每一层
generateUsers函数的$users变量都是独立副本,内层对$users的修改不会影响上层函数的$users值 - 原代码在递归调用语句后没有加终止逻辑,内层递归处理完剩余用户返回后,当前层函数还会继续执行后续的
count($users) === 1判断 - 当总用户数为奇数时,最后几次递归的上层函数的
$users副本在执行完配对、unset操作后,正好也只剩1个元素,就会重复触发插入「No Pair」记录的逻辑;偶数场景下所有层递归的$users最后都会被清空为0个,不会触发这个判断因此运行正常。
修复方案
只需要在递归调用语句后直接返回,避免当前层继续执行后续的多余判断即可,同时可移除冗余的matchedUsers相关逻辑,优化后代码示例:
class Match { protected $startingUsers = [ "User1", "User2", "User3", "User4", "User5", ]; protected $pairs = []; function getPairs(): array { if ($this->generateUsers($this->startingUsers)) { return $this->pairs; } return []; } function generateUsers(array $defaultUsers, array $updatedUsers = []): bool { $users = (!empty($updatedUsers)) ? $updatedUsers : $defaultUsers; if (count($users) > 1) { $randomUserIndex = rand(1, count($users) - 1); $this->pairs[] = [$users[0], $users[$randomUserIndex]]; unset($users[$randomUserIndex]); unset($users[0]); $newUsers = array_values($users); // 递归处理剩余用户后直接返回,不执行后续判断 return $this->generateUsers($this->startingUsers, $newUsers); } if (count($users) === 1) { $orderedUsers = array_values($users); $this->pairs[] = [$orderedUsers[0], "No Pair"]; } return true; } } $match = new Match(); foreach ($match->getPairs() as $pair) { echo "$pair[0] gets $pair[1]"; echo "\n"; }
内容的提问来源于stack exchange,提问作者DanHallsworth
相关产品推荐
相关产品推荐

