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

如何在JavaScript中通过排序实现数组的父子分组排列?

数组排序分组问题求解

需要实现数组元素的排序分组,规则如下:

  • 优先排列uniqueID非空且parentDocId为空的父元素,每个父元素紧随其后排列所有parentDocId等于该父元素uniqueID的子元素
  • 没有对应子元素的parentDocId为空的元素,需放在数组末尾

预期输出

[
    {
      name: 9,
      uniqueID: '22222',
      parentDocId: '',
    },
    {
      name: 11,
      uniqueID: '3463452345',
      parentDocId: '22222',
    },
    {
      name: 15,
      uniqueID: '3333',
      parentDocId: '',
    },
    {
      name: 19,
      uniqueID: '234235346',
      parentDocId: '3333',
    },
    {
      name: 346345,
      uniqueID: '11111',
      parentDocId: '',
    },
    {
      name: 7,
      uniqueID: '456456456',
      parentDocId: '11111',
    },
    {
      name: 55,
      uniqueID: '346345345',
      parentDocId: '',
    },
    {
      name: 77,
      uniqueID: '568567568567',
      parentDocId: '',
    },
];

实际输出

[
    {
        "name": 55,
        "uniqueID": "346345345",
        "parentDocId": ""
    },
    {
        "name": 77,
        "uniqueID": "568567568567",
        "parentDocId": ""
    },
    {
        "name": 7,
        "uniqueID": "456456456",
        "parentDocId": "11111"
    },
    {
        "name": 346345,
        "uniqueID": "11111",
        "parentDocId": ""
    },
    {
        "name": 19,
        "uniqueID": "234235346",
        "parentDocId": "3333"
    },
    {
        "name": 15,
        "uniqueID": "3333",
        "parentDocId": ""
    },
    {
        "name": 11,
        "uniqueID": "3463452345",
        "parentDocId": "22222"
    },
    {
        "name": 9,
        "uniqueID": "22222",
        "parentDocId": ""
    }
]

当前代码

items.sort((a, b) => {
    if (a.parentDocId === b.uniqueID) {
      return -1;
    } else if (b.parentDocId === a.uniqueID) {
      return 1;
    } else if (a.parentDocId === '' && b.parentDocId !== '') {
      return -1;
    } else if (a.parentDocId !== '' && b.parentDocId === '') {
      return 1;
    } else {
      return 0;
    }
});

问题分析

当前排序逻辑仅处理了相邻元素的父子关系,无法将父元素与对应子元素整体归组,也未区分有子元素的父和无子元素的父的优先级,导致子元素跑到父元素前面,且无子的父元素排在了最前面,不符合需求。

解决方案

采用分类拼接的方式更直观,逻辑清晰且不易出错:

// 1. 分离父元素(parentDocId为空且uniqueID非空)和子元素
const parents = items.filter(item => item.parentDocId === '' && item.uniqueID);
const children = items.filter(item => item.parentDocId !== '');

// 2. 建立父元素到其子元素的映射
const parentChildrenMap = new Map();
children.forEach(child => {
    if (!parentChildrenMap.has(child.parentDocId)) {
        parentChildrenMap.set(child.parentDocId, []);
    }
    parentChildrenMap.get(child.parentDocId).push(child);
});

// 3. 拆分父元素为「有子元素的父」和「无子元素的父」
const parentsWithChildren = parents.filter(p => parentChildrenMap.has(p.uniqueID));
const parentsWithoutChildren = parents.filter(p => !parentChildrenMap.has(p.uniqueID));

// 4. 构建最终结果:有子的父+对应子元素,再拼接无子的父
const sortedItems = [];
parentsWithChildren.forEach(parent => {
    sortedItems.push(parent);
    sortedItems.push(...parentChildrenMap.get(parent.uniqueID));
});
sortedItems.push(...parentsWithoutChildren);

如果需要保持原数组中父元素的相对顺序,上述代码中的filter方法会保留原数组的遍历顺序,完全匹配预期输出的排列逻辑。

内容的提问来源于stack exchange,提问作者Saint-Fons

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:05:13