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

嵌套对象递归过滤与属性设置问题求助

解决方案:嵌套对象按owner_id过滤并标记父级/匹配项

核心需求回顾

  • 按owner_id匹配对象,匹配项标记filtered: true
  • 匹配项的所有父级标记parented: true并保留
  • 递归处理最多4层嵌套结构,不能忽略被保留节点的任何子项(父级保留则子项必须保留,无论子项是否匹配)
  • 可利用扁平化数组,这里直接通过递归实现

实现思路

  1. 收集相关节点ID:先递归遍历整个结构,找出所有匹配owner_id的节点,同时收集这些节点的所有父级ID(确保父级被保留)
  2. 构建过滤后结构:再次递归遍历原结构,根据收集到的ID标记节点属性,同时确保被保留节点的所有子项都被保留(不管子项是否匹配)

完整代码实现

function filterNestedCardsByOwner(cards, targetOwnerId) {
  // 第一步:收集所有需要保留的节点ID(匹配节点 + 所有父级节点)
  const relevantNodeIds = new Set();
  
  function collectRelevantIds(nodes, currentPath = []) {
    for (const node of nodes) {
      const updatedPath = [...currentPath, node.id];
      // 如果当前节点匹配owner_id,把路径上所有节点ID加入集合
      if (node.owner_id === targetOwnerId) {
        updatedPath.forEach(id => relevantNodeIds.add(id));
      }
      // 递归处理子节点
      if (node.child_cards?.length) {
        collectRelevantIds(node.child_cards, updatedPath);
      }
    }
  }
  
  collectRelevantIds(cards);

  // 第二步:构建过滤后的结构,保留节点并标记属性
  function buildFilteredStructure(nodes, isParentKept = false) {
    const result = [];
    for (const node of nodes) {
      const isNodeRelevant = relevantNodeIds.has(node.id);
      // 节点保留条件:自身是相关节点,或父节点被保留
      const shouldKeepNode = isNodeRelevant || isParentKept;

      if (!shouldKeepNode) continue;

      // 创建节点副本,避免修改原数据
      const processedNode = { ...node };
      delete processedNode.child_cards;

      // 设置过滤标记
      if (node.owner_id === targetOwnerId) {
        processedNode.filtered = true;
      } 
      // 设置父级标记(自身不匹配但属于相关节点)
      else if (isNodeRelevant) {
        processedNode.parented = true;
      }

      // 递归处理子节点,传递父节点是否被保留的状态
      if (node.child_cards?.length) {
        processedNode.child_cards = buildFilteredStructure(node.child_cards, shouldKeepNode);
      }

      result.push(processedNode);
    }
    return result;
  }

  return buildFilteredStructure(cards);
}

测试示例

假设你的原始数据(补充id属性,需求说明所有对象包含id):

const objs = [
    {
        id: 1,
        title: 'title.1',
        owner_id: 1,
        child_cards: [
            {
                id: 11,
                title: 'title.1.1',
                owner_id: 2,
                child_cards: [
                    { id: 111, title: 'title.1.1.1', owner_id: 1 },
                    { id: 112, title: 'title.1.1.2', owner_id: 2 }
                ]
            },
            {
                id: 12,
                title: 'title.1.2',
                owner_id: 2,
                child_cards: [
                    { id: 121, title: 'title.1.2.1', owner_id: 1 }
                ]
            },
        ]
    },
    {
        id: 2,
        title: 'title.2',
        owner_id: 3,
        child_cards: [
            { id: 21, title: 'title.2.1', owner_id: 2 }
        ]
    },
    {
        id: 3,
        title: 'title.3',
        owner_id: 1,
        child_cards: [
            { id: 31, title: 'title.3.1', owner_id: 1 },
            { id: 32, title: 'title.3.2', owner_id: 1 },
            { id: 33, title: 'title.3.3', owner_id: 1 }
        ]
    }
];

调用函数过滤owner_id=2:

const filteredResult = filterNestedCardsByOwner(objs, 2);
console.log(JSON.stringify(filteredResult, null, 2));

输出结果(符合需求,保留所有被保留节点的子项):

[
  {
    "id": 1,
    "title": "title.1",
    "owner_id": 1,
    "parented": true,
    "child_cards": [
      {
        "id": 11,
        "title": "title.1.1",
        "owner_id": 2,
        "filtered": true,
        "child_cards": [
          {
            "id": 111,
            "title": "title.1.1.1",
            "owner_id": 1
          },
          {
            "id": 112,
            "title": "title.1.1.2",
            "owner_id": 2,
            "filtered": true
          }
        ]
      },
      {
        "id": 12,
        "title": "title.1.2",
        "owner_id": 2,
        "filtered": true,
        "child_cards": [
          {
            "id": 121,
            "title": "title.1.2.1",
            "owner_id": 1
          }
        ]
      }
    ]
  },
  {
    "id": 2,
    "title": "title.2",
    "owner_id": 3,
    "parented": true,
    "child_cards": [
      {
        "id": 21,
        "title": "title.2.1",
        "owner_id": 2,
        "filtered": true
      }
    ]
  }
]

说明

  • 代码会创建节点副本,不会修改原始数据
  • 严格遵循需求:匹配节点标记filtered:true,父级标记parented:true,被保留节点的所有子项都被保留(即使子项不匹配)
  • 自动处理最多4层嵌套结构,递归深度可适配实际层级

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:16:12