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

JavaScript移除嵌套数组指定元素的更优实现方案咨询

优化数组元素移除的实现方案

问题场景

给定如下数据结构,需要移除small_category(注意原数据存在拼写错误small_categor)数组中,code存在于deleteTargetCodeArr内的元素:

const parentArr = [
  {
    middle_code: "EX42",
    middle_name: "Checkup A",
    small_category:[{name: 'HAV Ab IgG', code: 'CH187'},{name: 'HAV Ab IgM', code: 'CH188'}] 
  },
  {
    middle_code: "EX42",
    middle_name: "Checkup B",
    small_categor:[{name: 'HAV Ab IgG', code: 'CH194'},{name: 'HAV Ab IgM', code: 'CH200'}, {name: 'HAV Ab IgM', code: 'CH201'}] 
  },
]
  
const deleteTargetCodeArr =['CH187', 'CH200'] 

期望得到的结果:

[
  {
    middle_code: "EX42",
    middle_name: "Checkup A",
    small_category:[{name: 'HAV Ab IgM', code: 'CH188'}] 
  },
  {
    middle_code: "EX42",
    middle_name: "Checkup B",
    small_categor:[{name: 'HAV Ab IgG', code: 'CH194'}, {name: 'HAV Ab IgM', code: 'CH201'}] 
  },
]

原实现代码虽然能运行,但存在修改原数据、迭代风险、效率较低的问题:

const resultArr = parentArr

resultArr.forEach((item)=> item.small_category.forEach((small, index1)=>{
  if(deleteTargetCodeArr.includes(small.code)){
    return item.small_category.splice(index1,1)
  }
}))

优化方案

方案1:纯函数式写法(不修改原数组,高效查找)

使用map创建新数组、filter过滤元素,同时将deleteTargetCodeArr转为Set,把查找复杂度从O(k)降为O(1)(k为目标数组长度),避免污染原数据:

const deleteTargetSet = new Set(deleteTargetCodeArr);

const resultArr = parentArr.map(item => {
  // 兼容原数据的拼写错误:small_category / small_categor
  const smallKey = 'small_category' in item ? 'small_category' : 'small_categor';
  return {
    // 浅拷贝原对象属性
    ...item,
    // 过滤掉需要删除的元素
    [smallKey]: item[smallKey].filter(small => !deleteTargetSet.has(small.code))
  };
});

优点:

  • 不修改原始数组,避免数据污染风险
  • 函数式写法逻辑清晰,可读性更高
  • Set查找效率远高于数组includes,适合大规模数据场景

方案2:原地修改优化(适合内存敏感场景)

如果必须原地修改原数组(避免创建新数组占用内存),可以优化遍历方式,从后往前遍历避免splice导致的索引偏移问题,同时用Set提升查找效率:

const deleteTargetSet = new Set(deleteTargetCodeArr);

parentArr.forEach(item => {
  const smallKey = 'small_category' in item ? 'small_category' : 'small_categor';
  const smallArr = item[smallKey];
  // 从后往前遍历,防止splice删除元素后导致后续元素索引错乱
  for (let i = smallArr.length - 1; i >= 0; i--) {
    if (deleteTargetSet.has(smallArr[i].code)) {
      smallArr.splice(i, 1);
    }
  }
});

优点:

  • 原地修改,内存占用低
  • 反向遍历避免了forEach+splice的漏删问题
  • Set查找优化了原代码的效率瓶颈

原代码的核心问题分析

  1. 修改原数据:resultArr = parentArr是引用赋值,修改resultArr的元素本质是修改原parentArr,会导致后续使用原数据时出现意外
  2. 迭代风险:forEach正向遍历+splice删除元素时,数组长度缩短,后续元素前移,会导致相邻的待删除元素被跳过
  3. 效率低下:数组includes是线性查找,每次判断都要遍历deleteTargetCodeArr,总时间复杂度为O(m*n*k)(m为父数组长度,n为子数组长度,k为目标数组长度),数据量大时性能很差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:55:20