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

为数组对象添加hierarchy属性时,使用lodash find遇parent未定义问题

问题描述

原始数组:

const arr = [
  {name: "Earth", id: 1, parent_id: -1},
  {name: "Europe", id: 2, parent_id: 1},
  {name: "America", id: 3, parent_id: 1},
  {name: "Asia", id: 4, parent_id: 1}
];

需求:为数组每个元素添加hierarchy键,使其包含层级名称数组,最终效果如下:

const arr = [
  {name: "Earth", id: 1, parent_id: -1, hierarchy: ["Earth"]},
  {name: "Europe", id: 2, parent_id: 1, hierarchy: ["Earth", "Europe"]},
  {name: "America", id: 3, parent_id: 1, hierarchy: ["Earth", "America"]},
  {name: "Asia", id: 4, parent_id: 1, hierarchy: ["Earth", "Asia"]}
];

尝试用Lodash的find方法实现,但始终得到parent === undefined的结果,代码如下:

const parent = _.find(arr, { id: val.parent_id });

if (parent === undefined) {
  val.hierarchy = [val.id];
} else {
  val.hierarchy = [...parent.hierarchy, val.id];
}
解决方案

问题原因分析

  1. 遍历顺序错误:如果先处理子节点再处理根节点,即使原数组存在父节点,也可能因父节点未完成hierarchy属性添加(或错误地在未构建完成的新数组中查找)导致找不到;另外根节点parent_id=-1时,原数组无对应id元素,这部分undefined是正常的,但原代码错误地将val.id存入hierarchy,不符合需求的名称要求。
  2. 查找逻辑缺陷:直接用_.find遍历数组找父节点,效率低且易受遍历顺序影响。

正确实现方式

方式一:构建ID映射表(推荐)

先将数组转为以id为键的映射表,快速查找任意节点,不受遍历顺序限制:

const arr = [
  {name: "Earth", id: 1, parent_id: -1},
  {name: "Europe", id: 2, parent_id: 1},
  {name: "America", id: 3, parent_id: 1},
  {name: "Asia", id: 4, parent_id: 1}
];

// 构建ID到节点的映射
const nodeMap = _.keyBy(arr, 'id');

// 遍历节点构建层级数组
const result = arr.map(node => {
  const hierarchy = [];
  let current = node;
  // 向上遍历直到根节点
  while (current) {
    hierarchy.unshift(current.name);
    current = nodeMap[current.parent_id];
  }
  return {...node, hierarchy};
});

console.log(result);

方式二:按层级顺序遍历

先处理根节点,确保子节点处理时父节点已完成hierarchy添加:

const arr = [
  {name: "Earth", id: 1, parent_id: -1},
  {name: "Europe", id: 2, parent_id: 1},
  {name: "America", id: 3, parent_id: 1},
  {name: "Asia", id: 4, parent_id: 1}
];

// 复制原数组避免修改原数据
const result = [...arr];

// 先处理根节点
const root = result.find(item => item.parent_id === -1);
root.hierarchy = [root.name];

// 处理一级子节点(多级嵌套需递归/层级遍历)
result.forEach(item => {
  if (item.parent_id !== -1) {
    const parent = result.find(p => p.id === item.parent_id);
    item.hierarchy = [...parent.hierarchy, item.name];
  }
});

console.log(result);

修复原代码逻辑

如果坚持使用原逻辑,需调整遍历顺序并修正层级内容:

const arr = [
  {name: "Earth", id: 1, parent_id: -1},
  {name: "Europe", id: 2, parent_id: 1},
  {name: "America", id: 3, parent_id: 1},
  {name: "Asia", id: 4, parent_id: 1}
];

// 先处理根节点
const root = _.find(arr, {parent_id: -1});
root.hierarchy = [root.name];

// 再处理其他节点
arr.forEach(val => {
  if (val.parent_id !== -1) {
    const parent = _.find(arr, { id: val.parent_id });
    val.hierarchy = [...parent.hierarchy, val.name];
  }
});

console.log(arr);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 01:45:57