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

如何按键前缀规则排序PHP对象数组并保留对象结构?

PHP对象数组按指定前缀排序并保留对象结构

问题背景

现有如下PHP对象数组:

$myWondersArray = [
    (object)[
        'currentUnitDisplay' => 'WonderSkills: Starter Book 2, Unit 3 - Helping Mom (Part 1/3)',
        'currentUnitPart' => 'wonderskills/starter_book_2/unit_3_helping_mom/part_1/',
    ],
    (object)[
        'currentUnitDisplay' => 'WonderSkills: Starter Book 2, Unit 3 - Helping Mom (Part 2/3)',
        'currentUnitPart' => 'wonderskills/starter_book_2/unit_3_helping_mom/part_2/',
    ],
    (object)[
        'currentUnitDisplay' => 'WonderSkills: Starter Book 2, Unit 3 - Helping Mom (Part 3/3)',
        'currentUnitPart' => 'wonderskills/starter_book_2/unit_3_helping_mom/part_3/',
    ],
    (object)[
        'previousUnitDisplay' => 'WonderSkills: Starter Book 2, Unit 2 - Sid\'s New Neighbors (Part 1/3)',
        'previousUnitPart' => 'wonderskills/starter_book_2/unit_2_sids_new_neighbors/part_1/',
    ],
    (object)[
        'previousUnitDisplay' => 'WonderSkills: Starter Book 2, Unit 2 - Sid\'s New Neighbors (Part 2/3)',
        'previousUnitPart' => 'wonderskills/starter_book_2/unit_2_sids_new_neighbors/part_2/',
    ],
    (object)[
        'previousUnitDisplay' => 'WonderSkills: Starter Book 2, Unit 2 - Sid\'s New Neighbors (Part 3/3)',
        'previousUnitPart' => 'wonderskills/starter_book_2/unit_2_sids_new_neighbors/part_3/',
    ],
    (object)[
        'nextUnitDisplay' => 'WonderSkills: Starter Book 2, Unit 4 - Food from the Garden (Part 1/3)',
        'nextUnitPart' => 'wonderskills/starter_book_2/unit_4_food_from_the_garden/part_1/',
    ],
    (object)[
        'nextUnitDisplay' => 'WonderSkills: Starter Book 2, Unit 4 - Food from the Garden (Part 2/3)',
        'nextUnitPart' => 'wonderskills/starter_book_2/unit_4_food_from_the_garden/part_2/',
    ],
    (object)[
        'nextUnitDisplay' => 'WonderSkills: Starter Book 2, Unit 4 - Food from the Garden (Part 3/3)',
        'nextUnitPart' => 'wonderskills/starter_book_2/unit_4_food_from_the_garden/part_3/',
    ],
];

需求:将数组中键以previous开头的对象排在最前,接着是键以current开头的对象,最后是键以next开头的对象,同时要保留对象本身结构不变,且每个分组内的原始顺序也需保留。

现有尝试的问题

之前尝试将对象拆分属性存入分组数组再合并,代码如下:

foreach($myWondersArray as $item => $value) {
    if($value->previousUnitDisplay){
        array_push($previousArray, $value->previousUnitDisplay, $value->previousUnitPart) ;
    }
} 
$completeWondersArray = array_merge($previousArray, $currentArray, $nextArray);

这种方式会把对象的属性拆成普通数组元素,直接丢失了原有的对象结构,无法满足需求。

解决方案

方案1:分组合并(直观易实现)

核心思路是直接将整个对象存入对应分组数组,而非拆分属性,最后合并三个分组数组即可。

// 初始化三个空分组数组
$previousGroup = [];
$currentGroup = [];
$nextGroup = [];

// 遍历原数组,按对象属性前缀分组
foreach ($myWondersArray as $obj) {
    if (property_exists($obj, 'previousUnitDisplay')) {
        $previousGroup[] = $obj;
    } elseif (property_exists($obj, 'currentUnitDisplay')) {
        $currentGroup[] = $obj;
    } elseif (property_exists($obj, 'nextUnitDisplay')) {
        $nextGroup[] = $obj;
    }
}

// 按要求顺序合并数组
$sortedArray = array_merge($previousGroup, $currentGroup, $nextGroup);

这种方法逻辑清晰,每个分组内的原始顺序会被完整保留,且对象结构完全不变。

方案2:自定义排序函数(灵活扩展)

使用usort自定义排序规则,给不同前缀的对象分配权重,通过权重大小实现排序。PHP 7.0+ 版本的usort是稳定排序,同权重的对象会保留原始顺序。

usort($myWondersArray, function($a, $b) {
    // 定义权重:previous < current < next
    $weightMap = [
        'previous' => 0,
        'current' => 1,
        'next' => 2
    ];

    // 获取对象对应的前缀类型
    $getType = function($obj) {
        if (property_exists($obj, 'previousUnitDisplay')) return 'previous';
        if (property_exists($obj, 'currentUnitDisplay')) return 'current';
        if (property_exists($obj, 'nextUnitDisplay')) return 'next';
        return null;
    };

    $aType = $getType($a);
    $bType = $getType($b);

    // 按权重差值排序
    return $weightMap[$aType] - $weightMap[$bType];
});

排序完成后,$myWondersArray即为符合要求的数组,对象结构和分组内顺序均保留。

内容的提问来源于stack exchange,提问作者Liam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:54:56