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查找优化了原代码的效率瓶颈
原代码的核心问题分析
- 修改原数据:
resultArr = parentArr是引用赋值,修改resultArr的元素本质是修改原parentArr,会导致后续使用原数据时出现意外 - 迭代风险:forEach正向遍历+splice删除元素时,数组长度缩短,后续元素前移,会导致相邻的待删除元素被跳过
- 效率低下:数组
includes是线性查找,每次判断都要遍历deleteTargetCodeArr,总时间复杂度为O(m*n*k)(m为父数组长度,n为子数组长度,k为目标数组长度),数据量大时性能很差
内容的提问来源于stack exchange,提问作者GaramSong
相关产品推荐
相关产品推荐

