JavaScript中过滤数组时同步截取另一数组的实现方法
解决filter回调中索引错位导致数组截取失败的问题
你遇到的问题其实很常见——因为filter遍历的是原数组的原始索引,而splice会直接修改outsideArray的长度,导致后续循环里的索引和修改后的数组对应关系完全乱掉了。举个例子:假设answers[user]是['a', '', 'b', ''],outsideArray初始是[1,2,4,5],当你在index=1的位置splice掉元素后,outsideArray变成[1,4,5],但filter接下来还是会按原数组的index=3去操作,这时候outsideArray已经没有index=3的元素了,自然会出错。
下面给你几种可行的解决方案,按直观程度排序:
方法1:同步遍历,同时收集两个数组的结果
这种方法最直观,直接遍历一次原数组,同时筛选answers[user]和outsideArray的有效元素,完全避开索引错位的问题:
const userAnswers = answers[user]; const endResult = []; const filteredOutsideArray = []; userAnswers.forEach((ans, index) => { if (ans !== '') { endResult.push(ans); filteredOutsideArray.push(outsideArray[index]); } }); // 如果你需要修改原outsideArray而不是生成新数组,可以这样: // outsideArray = filteredOutsideArray;
也可以用reduce写成更简洁的形式:
const { endResult, filteredOutside } = answers[user].reduce((acc, ans, idx) => { if (ans !== '') { acc.endResult.push(ans); acc.filteredOutside.push(outsideArray[idx]); } return acc; }, { endResult: [], filteredOutside: [] });
方法2:先收集需要保留的索引,再批量处理
先找出所有非空元素的索引,再用这些索引去提取两个数组的对应元素,逻辑清晰且不会破坏原数组:
const userAnswers = answers[user]; // 收集所有需要保留的索引 const keepIndices = userAnswers .map((ans, idx) => ans !== '' ? idx : null) .filter(idx => idx !== null); // 过滤answers[user] const endResult = keepIndices.map(idx => userAnswers[idx]); // 截取outsideArray const filteredOutsideArray = keepIndices.map(idx => outsideArray[idx]);
方法3:反向遍历数组进行splice
如果你一定要用splice修改原outsideArray,可以反向遍历数组。因为从后往前删除元素时,后面的索引变化不会影响前面还没处理的元素位置:
const userAnswers = answers[user]; // 注意:如果不想修改原outsideArray,先复制一份 const tempOutside = [...outsideArray]; // 从最后一个索引开始往前遍历 for (let i = userAnswers.length - 1; i >= 0; i--) { if (userAnswers[i] === '') { tempOutside.splice(i, 1); } } // 同时过滤answers[user] const endResult = userAnswers.filter(ans => ans !== ''); // 原outsideArray如果需要替换的话: // outsideArray = tempOutside;
这几种方法都能解决索引错位的问题,其中方法1和2更推荐,因为逻辑清晰,不容易出错,也不会产生意外的数组修改副作用。
内容的提问来源于stack exchange,提问作者henry
相关产品推荐
相关产品推荐

