PHP多维数组赋值前的邻居ID条件比较问题求助
解决方案:基于已分配ID的邻避规则实现ID分配
我来帮你一步步实现这个逻辑,核心是先从多维数组里提取最新已分配的ID,再匹配它的邻避列表,最后筛选出符合条件的待分配ID,避免陷入无限跳过的循环。
步骤拆解
- 提取$schedule中最新已分配的ID:遍历整个多维数组,收集所有非空的ID,取最后一个就是最近分配的那个。
- 构建ID到邻避列表的映射:把
$idAndNeighbour转换成更易查询的结构,方便快速获取某个ID对应的所有邻避ID。 - 筛选符合条件的待分配ID:遍历待分配ID队列,找到第一个不在邻避列表里的ID,这就解决了“仅在$idAndNeighbour内比较导致持续跳过”的问题。
- 分配ID到$schedule:把选中的ID填充到$schedule的第一个空位置。
完整代码实现
<?php // 原始数组定义 $schedule = array( 0 => array( // day 0 0 => array( // session 1 0 => array( // room 405 0 => "5" // id from arr2 ), 1 => array( // room 406 0 => "7" ), 2 => array( // room 407 0 => "" ), 3 => array( // room 408 0 => "" ) ) ) ); $idAndNeighbour = array( 0 => array( 'id'=>5, 'neighbour1' => 4, 'neighbour5' => 22, ), 1 => array( 'id'=>7, 'neighbour1' => 9, 'neighbour5' => 24, ), 2 => array( 'id'=>9, 'neighbour1' => 7, 'neighbour5' => 23, ), 3 => array( 'id'=>14, 'neighbour1' => 8, 'neighbour5' => 26, ) ); // 待分配ID队列,按优先级排序 $pendingIds = [9, 14]; // 1. 收集所有已分配的非空ID $assignedIds = []; array_walk_recursive($schedule, function($value) use (&$assignedIds) { if (!empty($value)) { $assignedIds[] = (int)$value; } }); // 2. 构建ID到邻避列表的映射 $idToNeighbours = []; foreach ($idAndNeighbour as $item) { $id = $item['id']; // 提取所有以neighbour开头的字段值 $neighbours = array_filter($item, function($key) { return str_starts_with($key, 'neighbour'); }, ARRAY_FILTER_USE_KEY); $idToNeighbours[$id] = array_values($neighbours); } // 3. 筛选符合条件的待分配ID $selectedId = null; if (empty($assignedIds)) { // 初始无已分配ID,直接取第一个待分配ID $selectedId = reset($pendingIds); } else { $lastAssignedId = end($assignedIds); $forbiddenIds = $idToNeighbours[$lastAssignedId] ?? []; foreach ($pendingIds as $id) { if (!in_array($id, $forbiddenIds)) { $selectedId = $id; break; } } } // 处理所有待分配ID都被禁止的边界情况 if ($selectedId === null) { throw new Exception("All pending IDs are forbidden to assign next."); } // 4. 将选中的ID分配到$schedule的第一个空位置 $assigned = false; array_walk_recursive($schedule, function(&$value) use ($selectedId, &$assigned) { if (empty($value) && !$assigned) { $value = (string)$selectedId; $assigned = true; } }); // 输出结果 print_r($schedule); ?>
代码说明
- 多维数组遍历:用
array_walk_recursive可以轻松遍历嵌套的$schedule数组,不用写多层循环,简洁高效。 - 映射构建:把
$idAndNeighbour转换成ID => [neighbour1, neighbour5...]的结构,查询邻避列表的效率更高,也更易维护。 - 边界处理:考虑了初始无已分配ID和所有待分配ID都被禁止的情况,避免程序崩溃或陷入死循环。
- 分配逻辑:找到$schedule中第一个空位置填充选中的ID,确保分配位置的合理性。
运行这段代码后,$schedule中room407的位置会被填充为14——因为9是最后已分配ID7的邻避ID,所以被跳过,改用下一个符合条件的ID14,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Felix Candra
相关产品推荐
相关产品推荐

