You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:45:43