PHP中如何按weight值偏移数组元素键?求高效实现方案
看起来你遇到了一个挺有意思的数组重排问题,我来帮你梳理下最高效的实现方式~
首先明确需求:你需要把数组中的每个元素,移动到原键 + 元素自身weight值对应的位置。从给出的示例来看,当元素weight为-1时,它会和左侧相邻位置的元素交换(比如原键2的元素移到1),而weight为0的元素虽原本应留在原地,最终却被交换到右侧——这本质是因为移动的元素占据了它的位置,形成了双向交换。
最高效的实现思路
最高效的实现分为两种场景:如果允许修改原数组,优先用原地交换(空间开销极小);如果需要保留原数组,就用构建新数组的方式(更安全),两种方案的时间复杂度都是O(n),属于线性遍历,效率拉满。
方案1:原地交换(空间复杂度O(1),推荐用于大规模数组)
这种方式直接在原数组上操作,只需要临时变量存储交换元素,避免额外的数组拷贝开销:
function reorderArray(&$array) { // 获取所有键并排序,确保按顺序处理避免重复交换 $keys = array_keys($array); sort($keys); foreach ($keys as $key) { // 跳过已被交换处理过的键 if (!isset($array[$key])) continue; $item = $array[$key]; $targetKey = $key + $item['weight']; // 目标位置有效且不等于当前键时,执行交换 if (isset($array[$targetKey]) && $targetKey !== $key) { // 临时存储目标位置的元素 $temp = $array[$targetKey]; // 交换元素 $array[$targetKey] = $item; $array[$key] = $temp; // 移除已处理的目标键,避免重复遍历 $index = array_search($targetKey, $keys); if ($index !== false) { unset($keys[$index]); } } } return $array; } // 测试用例 $my_array = [ 1 => ["id" => 1, "weight" => 0], 2 => ["id" => 2, "weight" => -1], 3 => ["id" => 3, "weight" => 0], 4 => ["id" => 4, "weight" => -1], ]; reorderArray($my_array); print_r($my_array);
方案2:构建新数组(更安全,保留原数组)
如果不想修改原数组,或者需要保留原始数据,可以直接基于原数组的规则构建新数组,逻辑更直观:
function reorderArray($array) { $newArray = []; // 记录元素的原键与目标键映射,处理交换场景 $mappings = []; foreach ($array as $key => $item) { $targetKey = $key + $item['weight']; // 如果目标位置已经被其他元素占用,说明需要交换:把原目标位置的元素放到当前键 if (isset($mappings[$targetKey])) { $newArray[$key] = $array[$mappings[$targetKey]]; } // 将当前元素放到目标位置 $newArray[$targetKey] = $item; // 记录当前元素的原键,用于处理后续冲突 $mappings[$targetKey] = $key; } // 补充那些weight为0且未被交换的元素(确保所有键都被填充) foreach ($array as $key => $item) { if (!isset($newArray[$key])) { $newArray[$key] = $item; } } // 按键排序,保持原数组的键顺序 ksort($newArray); return $newArray; } // 测试用例 $my_array = [ 1 => ["id" => 1, "weight" => 0], 2 => ["id" => 2, "weight" => -1], 3 => ["id" => 3, "weight" => 0], 4 => ["id" => 4, "weight" => -1], ]; $result = reorderArray($my_array); print_r($result);
为什么这两种方案高效?
- 两种方案都是线性时间复杂度O(n),只需要遍历数组1-2次,没有嵌套循环,处理速度随数组规模线性增长。
- 原地交换方案的空间复杂度接近O(1)(仅额外存储键列表,可进一步优化),适合处理超大数组;构建新数组的空间复杂度是O(n),但逻辑更清晰,不会修改原数组,适合需要保留原始数据的场景。
测试结果
两种方案运行后都会得到你期望的结果:
Array ( [1] => Array ( [id] => 2 [weight] => -1 ) [2] => Array ( [id] => 1 [weight] => 0 ) [3] => Array ( [id] => 4 [weight] => -1 ) [4] => Array ( [id] => 3 [weight] => 0 ) )
内容的提问来源于stack exchange,提问作者Antoine Aïello
相关产品推荐
相关产品推荐

