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

如何对对象数组排序:确保父ID对应对象排在子对象之前

需求:按父节点优先规则排序对象数组

现有数组

let arrOfObjs = [
{
    "id": "unique1",
    "parentId": "unique3", // 等于arrOfObjs[2].id
    "title": "title1"
}, 
{
    "id": "unique2",
    "parentId": "unique3", // 同样等于arrOfObjs[2].id
    "title": "title2"
}, 
{
    "id": "unique3",
    "parentId": "",
    "title": "title3"
}
]

已知条件

  • id始终唯一
  • parentId对应数组中某一对象的id,允许重复

排序目标

确保父对象(id被其他对象的parentId引用)始终排在所有子对象之前。示例中unique3作为父节点,需排在unique1和unique2前面,最终期望结果:

let arrOfObjs = [
{
    "id": "unique3",
    "parentId": "",
    "title": "title3"
},
{
    "id": "unique2",
    "parentId": "unique3", 
    "title": "title2"
}, 
{
    "id": "unique1",
    "parentId": "unique3",
    "title": "title1"
}
]

实现方案

方法一:依赖映射+自定义排序

适合简单层级场景,通过快速映射和排序函数直接调整顺序:

  1. 先构建id到对象的映射表,避免重复遍历数组查找父节点
  2. 自定义排序逻辑,直接对比两个对象的父子关系,同时处理多层嵌套的层级对比
// 构建id到对象的映射
const idMap = arrOfObjs.reduce((map, obj) => {
    map[obj.id] = obj;
    return map;
}, {});

// 执行排序
arrOfObjs.sort((a, b) => {
    // 若b的父节点是a,a优先排前
    if (b.parentId === a.id) return -1;
    // 若a的父节点是b,b优先排前
    if (a.parentId === b.id) return 1;

    // 处理多层嵌套:获取节点的顶层父节点层级
    const getTopLevel = (obj, level = 0) => {
        if (!obj.parentId) return level;
        return getTopLevel(idMap[obj.parentId], level + 1);
    };
    const levelA = getTopLevel(a);
    const levelB = getTopLevel(b);

    // 层级越小(越顶层)排越前
    return levelA - levelB;
});

方法二:拓扑排序

适合复杂多层嵌套场景,能彻底解决所有依赖顺序问题,确保所有父节点都排在子节点之前:

  1. 构建节点的子节点列表和入度统计(入度表示该节点有多少父依赖)
  2. 从根节点(无parentId)开始,依次处理节点并减少子节点的入度,入度为0时说明该节点的所有父节点已处理完成,可加入结果
const sortByParentPriority = (arr) => {
    const idMap = {};
    const childrenMap = {};
    const inDegree = {};

    // 初始化映射结构
    arr.forEach(obj => {
        idMap[obj.id] = obj;
        childrenMap[obj.id] = childrenMap[obj.id] || [];
        inDegree[obj.id] = inDegree[obj.id] || 0;
        
        if (obj.parentId) {
            childrenMap[obj.parentId].push(obj.id);
            inDegree[obj.id]++;
        }
    });

    // 初始化队列:所有根节点(无父节点)
    const queue = arr.filter(obj => !obj.parentId).map(obj => obj.id);
    const result = [];

    while (queue.length) {
        const currentId = queue.shift();
        result.push(idMap[currentId]);

        // 处理当前节点的所有子节点,入度减1,入度为0则加入队列
        childrenMap[currentId].forEach(childId => {
            inDegree[childId]--;
            if (inDegree[childId] === 0) queue.push(childId);
        });
    }

    return result;
};

// 使用示例
const sortedArr = sortByParentPriority(arrOfObjs);
console.log(sortedArr);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 12:30:53