双重for
//双重循环去重
const handleRemoveRepeat = (arr) => {
for (let i=0,len = arr.length; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1); //从下标j,删除一位
j--; //删除了一位,数组长度减一,arr[i]还是要和原来的同样下标的arr[j]比较,j++了,就j--回到原来的位置
len--; // 删除一位,数组长度减一,相对要比较的次数也要减一
}
}
}
return arr;
};
被圈起来的三个表示的是for循环的三个表达式,依次分别是:初始表达式,判断表达式,自增表达式。其中,初始表达式在for循环开始的时候会执行一次,以后就不会再执行了,但是判断表达式和自增表达式会在每一次循环的时候都去执行。
但这和我们一开始len = arr.length有什么关系呢?
值得注意的是,如果一开始定义,那么每一次循环,都需要走 arr.length,length可是个方法,虽然他的消耗并不大,但在for循环中这个消耗会被方法,假设这个循环需要循环10000次呢,length就会被执行10000次。
es6 --set去重
new Set是ES6新推出的一种类型。他和数组的区别在于,Set类型中的数据不可以有重复的值。当然,数组的一些方法Set也无法调用。 使用方法:其实很简单,将一个数组转化为Set数据,再转化回来,就完成了去重。
const arr = [1,1,2,2,3,3,4,4,5,5];
// const setData = Array.from(new Set(arr));
const setData=[...new Set(arr)]
console.log(setData);
但是Set去重有一个弊端,他无法去重引用类型的数据。比如对象数组。
indexOf()
使用includes的去重方法和indexOf不能说很像,基本上一模一样。变换的仅仅只是判断方法。
//去重
const handleRemoveRepeat = (arr) => {
let repeatArr = [];
for (let i = 0,len = arr.length ; i < len; i++)
if (repeatArr.indexOf(arr[i]) === -1) repeatArr.push(arr[i]) // 没有找到,才放在新的数组中
return repeatArr;
}
同样的,这个方法也有一个细节点,您或许已经发现了,上文的if和for没有花括号;是的;for和if都默认对下面一条语句负责。在没有必要的情况下,不用多加一个{}。
includes
const handleRemoveRepeat = (arr) => {
let repeatArr = [];
for (let i = 0,len = arr.length ; i < len; i++)
if (!repeatArr.includes(arr[i])) repeatArr.push(arr[i])
return repeatArr;
}
filter
使用filter配合indexOf进行的去重过程,真的可以非常的简单且富含趣味性。
//去重
const handleRemoveRepeat = (arr) => arr.filter((item,index) => arr.indexOf(item,0) === index);
对象数组去重
const arrobj=[
{
id:1,
name:'x'
},
{
id:2,
name:'y'
},
{
id:1,
name:'k'
}
]
function fn(arr){
const res=[]
const maplist=new Map()
arr.forEach(e => {
if(!maplist.has(e.id)){
res.push(e) //e 是数据中每一个对象, 根据Map的属性都不一样,来去重,当Map 没有这个属性,才把这个对象放在新的数组中,并把这个对象的属性放在Map中,方便下次判断
maplist.set(e.id,true)
}
});
return res
}