js两个嵌套的循环如何让数值正确的删除
问题
js两个嵌套的循环如何让数值正确的删除
由大模型辅助整理,保留原意,优化结构与可读性。
问题概述
提问者在处理一个二维数组(外层数组包含多个子数组,每个子数组是若干对象)时,希望在两层嵌套循环中根据条件删除/筛选内层数组中的元素,并得到正确结果,但对 forEach、filter、map 等数组方法的选择感到困惑。
涉及技术
JavaScript、数组方法(forEach、filter、map、splice)、正则表达式
期望结果
在嵌套的二维数组结构中,正确地按条件保留(或删除)内层数组中的元素,最终得到期望的筛选结果,例如示例中希望拿到 {a:11,b:11} 这一条数据。
回答
原始回答
2018-03-05
item2.splice(index2,1); //item2item是外层的,你要删除的是内层的。所以是item2**
仔细一看,我应该写错了。我再改改
forEach() 方法对数组的每个元素执行一次提供的函数。应用场景:为一些相同的元素,绑定事件处理器!
那么forEach看上去不那么适合
filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
filter()也不适合,他只有两个操作,要或者不要,所以最外层的循环他改变不了
map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
这个我觉得就还好了,因为他是一个返回值的合集
var patt = new RegExp(11);
var data = [
[
{a:1,b:1},
{a:2,b:2},
{a:3,b:3}
],
[
{a:11,b:11},
{a:22,b:22},
{a:33,b:33}
]
]
data = data.map((item,index) => {
item = item.filter((item2,index2) => {
console.log(item2)
return patt.test(item2.a)
});
return item
});
console.log(data); //我希望这个data能拿到的是{a:11,b:11}这一条数据
AI 优化 · 回答整理
解答思路
在嵌套循环中删除元素时要注意“你要删除的是哪一层”:如果用 splice 直接操作内层数组,需要格外小心索引错位的问题;更稳妥的做法是外层用 map 生成新数组,内层用 filter 按条件筛选出需要保留的元素,两者组合既能避免索引错乱,又能直观表达“筛选”这个语义。
示例代码
var patt = new RegExp(11);
var data = [
[
{ a: 1, b: 1 },
{ a: 2, b: 2 },
{ a: 3, b: 3 }
],
[
{ a: 11, b: 11 },
{ a: 22, b: 22 },
{ a: 33, b: 33 }
]
];
data = data.map((item, index) => {
item = item.filter((item2, index2) => {
console.log(item2);
return patt.test(item2.a);
});
return item;
});
console.log(data); // 希望这个 data 能拿到的是 {a:11,b:11} 这一条数据
详细说明
item2.splice(index2, 1)的坑:直接在内层循环里用splice删除元素,如果一边遍历一边删除,后续元素的索引会跟着往前移,容易导致漏删或多删,这也是最初思路里踩的坑。- 为什么不用
forEach:forEach只是单纯遍历执行回调,没有返回值,不适合用来“生成一个筛选后的新结果”,更适合做绑定事件之类的副作用操作。 - 为什么不完全适合单独用
filter:filter只能对一层数组做“要或不要”的布尔判断,无法同时处理“外层要不要变、内层要不要变”这种两层结构的场景,所以最外层这一层的结构本身没法只靠一次filter解决。 - 最终方案
map+filter:外层用map遍历每个子数组并返回一个新的子数组(保持外层结构不变),内层对每个子数组用filter,通过正则patt.test(item2.a)判断a字段是否包含11,只保留满足条件的对象。这样处理完之后,data的结构不变(仍是二维数组),但内层数组只留下了匹配的元素。
小结
处理嵌套数组的筛选/删除问题时,优先考虑用 map(处理外层,保持结构)搭配 filter(处理内层,做条件筛选)的组合方案,比手动 splice 更不容易出现索引错位的问题,代码也更符合声明式的函数式编程风格。
由大模型辅助整理,保留原意,补充结构与代码格式。
回答转载自 SegmentFault