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

如何通过含uid的路径数组过滤嵌套JavaScript对象?

基于UID路径过滤嵌套对象的正确实现

你的原代码核心问题是处理数组时,每次匹配到UID都会直接向过滤结果的数组中push新对象,导致同一条目重复添加。下面是修正后的实现方案,解决重复条目问题:

修正后的完整代码

const SEPARATOR = '.';

const filterDataByPath = (originalData, path, filteredData = {}) => {
  const pathChunks = path.split(SEPARATOR);
  const currentChunk = pathChunks[0];
  const remainingPath = pathChunks.slice(1).join(SEPARATOR);

  // 处理普通属性键的情况
  if (originalData.hasOwnProperty(currentChunk)) {
    const originalValue = originalData[currentChunk];
    // 若为对象/数组且还有剩余路径,递归处理
    if (typeof originalValue === 'object' && originalValue !== null && remainingPath) {
      filteredData[currentChunk] = filterDataByPath(
        originalValue,
        remainingPath,
        filteredData[currentChunk] || (Array.isArray(originalValue) ? [] : {})
      );
    } else {
      // 直接赋值属性值
      filteredData[currentChunk] = originalValue;
    }
  } else {
    // 处理UID匹配数组元素的情况
    const [arrayKey, targetItem] = Object.entries(originalData).reduce((result, [key, value]) => {
      if (Array.isArray(value)) {
        const found = value.find(item => item.uid === currentChunk);
        if (found) return [key, found];
      }
      return result;
    }, []);

    if (!arrayKey || !targetItem) {
      throw new Error(`路径无效,未找到匹配的块:${currentChunk}`);
    }

    // 确保过滤结果中对应数组存在
    if (!filteredData[arrayKey]) {
      filteredData[arrayKey] = [];
    }

    // 查找过滤结果数组中是否已存在该UID的对象,避免重复
    let existingItem = filteredData[arrayKey].find(item => item.uid === currentChunk);
    if (!existingItem) {
      existingItem = { uid: currentChunk };
      filteredData[arrayKey].push(existingItem);
    }

    // 递归处理剩余路径,复用已存在的对象
    if (remainingPath) {
      filterDataByPath(targetItem, remainingPath, existingItem);
    }
  }

  return filteredData;
};

// 使用示例
const obj = {
  topLevelProp1: 'some',
  topLevelProp2: 'data',
  topLevelPropArr: [{
    uid: 'd7ed3623-e431-4bfa-85b3-8da14fa399c3',
    secLevelProp1: 123,
    secLevelPropArr: [{
      uid: '15562309-22b7-4b11-a12e-b3374f0a7636',
      thirdLevelProp1: 'a plain value',
      thirdLevelProp2: {
        a: 'I am',
        b: 'a nested',
        c: 'object',
      },
    }, {
      uid: '9394f313-b7bf-45fa-b8f3-683832ff7aa2',
      thirdLevelProp1: null,
      thirdLevelProp2: {
        a: 'I am also',
        b: 'another nested',
        c: 'object !!!',
      },
    }],
  }, {
    uid: '04a487c6-9624-4b2e-8411-59a69c14f1e3',
    secLevelProp1: 456,
    secLevelPropArr: [{
      uid: '58d4a3fd-734c-4c22-a0e3-f669e6ec7af3',
      thirdLevelProp1: 'another plain value',
    }],
  }],
};

const paths = [
  'topLevelProp2',
  '04a487c6-9624-4b2e-8411-59a69c14f1e3.secLevelProp1',
  'd7ed3623-e431-4bfa-85b3-8da14fa399c3.9394f313-b7bf-45fa-b8f3-683832ff7aa2.thirdLevelProp2.a',
  'd7ed3623-e431-4bfa-85b3-8da14fa399c3.9394f313-b7bf-45fa-b8f3-683832ff7aa2.thirdLevelProp2.c',
];

let filteredData = {};
paths.forEach(path => {
  filteredData = filterDataByPath(obj, path, filteredData);
});

console.log(JSON.stringify(filteredData, null, 2));

关键修改说明

  1. 避免数组重复条目:处理UID匹配的数组元素时,先在过滤结果的对应数组中查找是否已存在该UID的对象,存在则复用,不存在才创建新对象并入数组。
  2. 递归复用已有对象:递归处理剩余路径时,传入已存在的对象,确保同一路径的属性会合并到同一个对象中,不会生成新对象。
  3. 修复路径处理逻辑:用slice(1)替代splice(1),避免修改原路径数组(splice会改变原数组,导致后续逻辑出错)。
  4. 完善空值判断:增加originalValue !== null的判断,避免null被误判为对象处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 02:30:02