前端实习生的这个 bug 被用做了一道基础面试题
The following article is from 前端界 Author 芝士
来源:前端界 (ID: gh_be76678b7c8b)
作者:黄茜琳
前言
测试发现了一个问题,简单描述问题就是通过函数删除一个数组中多个元素,传入的参数是一个数组索引。
然后发现实际效果有时删除的不是想要的内容。
具体 Bug
代码实现:
const arr = [1,2,3,4,5,6,7];
const removeData = (rowIndexs:Array<number>)=>{
if(Array.isArray(rowIndexs)){
rowIndex.forEach((index)=>{
arr.splice(index,1)
})
}
}
removeData([1,4]);
console.log(arr); // 输出结果 [1,3,4,5,7]
// 期望输出结果 [1,3,4,6,7]
上面代码出现问题的原因是 splice
会改变原始数组的,然后导致索引偏移,不知道有没有同学出过类似问题。
因为这个 bug
我发现有些同学基础该是比较差,导致一些不必要的问题,于是把它变成了一道基础面试题,注意考基础,同时删除数组中的多个元素利用索引数组有多少种方式,把可以想到的方法都写一下哦(其实不是为了难为人,知识想考察一下面试者javaScript
的基础编写能力) 接下来介绍这几种方法,欢迎补充
方法一:先倒序后删除
这种方式将参数索引数组按照从大到小排序,避免了删除元素导致的索引偏移
const arr = [1,2,3,4,5,6];
const removeMultipleElement = (rowIndexs)=>{
// 先倒序
if(Array.isArray(rowIndexs)){
rowIndexs = rowIndexs.sort((a,b)=>b-a);
rowIndex.forEach((rowIndex)=>{
arr.splice(rowIndex,1);
})
}
}
removeMultipleElement([1,4]);
console.log(arr);
方法二:使用filter生成新数组
使用
filter
生成新数组,并且结合includes
。(注意filter
过滤的内容是浅拷贝过程)
const arr = [1,2,3,4,5,6];
cons removeMultipleElement = (rowIndexs)=>{
if(Array.isArray(rowIndexs)){
arr = arr.filter((_,index)=>!rowIndex.includes(index))
}
}
removeMultipleElement([1,4]);
console.log(arr);
方法三:使用reduce生成新数组
使用
reduce
和includes
函数,也会生成新数组
const arr = [1,2,3,4,5,6];
cons removeMultipleElement = (rowIndexs)=>{
if(Array.isArray(rowIndexs)){
arr = arr.reduce((prev,current,currentIndex)=>{
if(!rowIndexs.includes(rowIndex)){
prev.push(current)
}
return prev
},[])
}
}
removeMultipleElement([1,4]);
console.log(arr);
方法四:生成新数组,判断用Set.has 替换 includes
仍然会生成新数组,只是
includes
判断使用set.has
替换,set.has
判断会比includes
的性能好一些,但是也要考虑数组数据量的大小,如果只是几个值,可以不考虑
const arr = [1,2,3,4,5,6];
let newArr = [];
cons removeMultipleElement = (rowIndexs)=>{
const rowIndexsSet = new Set(rowIndex);
arr.forEach((item,index)=>{
if(!rowIndexSet.has(index)){
newArr.push(item)
}
})
}
removeMultipleElement([1,4]);
console.log(arr);
方法五:标记删除法加 filter
创建一个与原始数组相同长度的布尔数组
markedForDeletion
,用于标记需要删除的元素。然后,我们遍历索引数组,将对应的标记设置为true
。最后,我们使用filter
方法创建一个新数组,只保留未被标记为删除的元素。
const arr = [1,2,3,4,5,6];
cons removeMultipleElement = (rowIndexs)=>{
const markedForDeletion = new Array(arr.length).fill(false);
for(const index of rowIndexs){
markedForDeletion[index] = true;
}
arr = arr.filter((_,index)=>!markedForDeletion[index])
}
removeMultipleElement([1,4]);
console.log(arr);
总结
目前针对这道题函数删除一个数组中多个元素,传入的参数是一个数组索引总结了几种解法,也避免了最初的 bug
,欢迎大家评论提供更多的方法。