js两个嵌套的循环如何让数值正确的删除

思否 问答 已采纳 👍 2 含 AI 优化版

问题

js两个嵌套的循环如何让数值正确的删除

在 SegmentFault 查看原问题 →

由大模型辅助整理,保留原意,优化结构与可读性。

问题概述

提问者在处理一个二维数组(外层数组包含多个子数组,每个子数组是若干对象)时,希望在两层嵌套循环中根据条件删除/筛选内层数组中的元素,并得到正确结果,但对 forEachfiltermap 等数组方法的选择感到困惑。

涉及技术

JavaScript、数组方法(forEachfiltermapsplice)、正则表达式

期望结果

在嵌套的二维数组结构中,正确地按条件保留(或删除)内层数组中的元素,最终得到期望的筛选结果,例如示例中希望拿到 {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 删除元素,如果一边遍历一边删除,后续元素的索引会跟着往前移,容易导致漏删或多删,这也是最初思路里踩的坑。
  • 为什么不用 forEachforEach 只是单纯遍历执行回调,没有返回值,不适合用来“生成一个筛选后的新结果”,更适合做绑定事件之类的副作用操作。
  • 为什么不完全适合单独用 filterfilter 只能对一层数组做“要或不要”的布尔判断,无法同时处理“外层要不要变、内层要不要变”这种两层结构的场景,所以最外层这一层的结构本身没法只靠一次 filter 解决。
  • 最终方案 map + filter:外层用 map 遍历每个子数组并返回一个新的子数组(保持外层结构不变),内层对每个子数组用 filter,通过正则 patt.test(item2.a) 判断 a 字段是否包含 11,只保留满足条件的对象。这样处理完之后,data 的结构不变(仍是二维数组),但内层数组只留下了匹配的元素。

小结

处理嵌套数组的筛选/删除问题时,优先考虑用 map(处理外层,保持结构)搭配 filter(处理内层,做条件筛选)的组合方案,比手动 splice 更不容易出现索引错位的问题,代码也更符合声明式的函数式编程风格。

由大模型辅助整理,保留原意,补充结构与代码格式。

回答转载自 SegmentFault

评论

评论功能即将开放。你也可以通过 邮件GitHub Issue 反馈。