通八洲科技

如何递归过滤嵌套对象数组中指定 _id 的所有节点(无论层级深浅)

日期:2025-12-29 00:00 / 作者:霞舞

本文介绍一种通用的递归函数实现,用于从任意深度嵌套的对象数组中移除所有 `_id` 匹配的目标项(包括顶层元素及其子级 `assets` 中的节点),并保持其余结构完整。

在处理树形或嵌套结构的数据(如带子资源的文档、菜单、权限配置等)时,常需根据唯一标识(如 _id)精准剔除某节点——该节点可能位于顶层,也可能深藏于多层 assets、children 或其他自定义子数组中。此时,简单的 filter() 或 findIndex() 无法覆盖全路径,必须采用递归遍历 + 原地过滤策略。

以下是一个健壮、可复用的递归过滤函数:

function removeIdFromArray(array, idToRemove) {
  if (!Array.isArray(array)) return array;

  return array.filter((element) => {
    // 若当前元素自身_id匹配,直接排除(不进入子级处理)
    if (element._id === idToRemove) {
      return false;
    }

    // 若存在子数组(如 assets),递归处理并更新引用
    if (Array.isArray(element.assets)) {
      element.assets = removeIdFromArray(element.assets, idToRemove);
    }

    // 保留该元素(即使其子级被删减,只要自身未被移除即返回 true)
    return true;
  });
}

使用示例:

const arrayToBeFiltered = [
  { _id: "1", assets: [{ _id: "2" }, { _id: "3" }] },
  { _id: "4", assets: [{ _id: "5" }] }
];

// 移除 _id === "3" → 仅删除第二项中的子对象
console.log(removeIdFromArray(arrayToBeFiltered, "3"));
// 输出:
// [
//   { _id: "1", assets: [{ _id: "2" }] },
//   { _id: "4", assets: [{ _id: "5" }] }
// ]

// 移除 _id === "4" → 删除整个第二项(顶层匹配)
console.log(removeIdFromArray(arrayToBeFiltered, "4"));
// 输出:
// [
//   { _id: "1", assets: [{ _id: "2" }, { _id: "3" }] }
// ]

⚠️ 注意事项:

该方案简洁、高效、无副作用,适用于前端状态管理、API 响应预处理及配置驱动型 UI 的动态数据裁剪场景。