数组去重的方式有不少种,咱们先拿出3种比较简单的进行学习;javascript
原理:依次遍历数组中的每一项,拿当前项和其“后面”的每一项进行比较,若是后面中有和他相同的,则说明这项是重复的,咱们把后面中重复的这一项删除掉便可java
let arr = [1, 1, 1, 2, 2, 3, 2, 2, 1, 2, 3, 2, 1, 2, 2, 3];
//====外层循环控制每一次拿出一项和其后面的比
// i < arr.length - 1 最后一项不须要再拿出来了,由于每一次都是和当前项后面的比较,而最后一项后面没有任何的东西,因此也就没有必要再拿出来比较了
for (let i = 0; i < arr.length - 1; i++) {
// 每一次拿出来要和后面依次比较的那一项
let item = arr[i];
//====里层循环控制和当前项后面的每一项逐一比较
// let j = i + 1 从当前项的后一项开始逐一比较便可
for (let j = i + 1; j < arr.length; j++) {
if (item === arr[j]) {
// 当前项和后面中的某一项相等了,此时咱们把后面中的这一项从原始数组中删除掉
arr.splice(j, 1);
j--; //=>删除完,先让j--,而后在j++,至关于没加没减,下一轮仍是从当前索引开始比较,这样防止数组塌陷带来的问题
}
}
}
复制代码
解决完
splice
引发的塌陷问题后咱们已经能够实现想要的效果,可是根据上图咱们能够知道,数组
- 在删除重复项后后面每一项的索引都会向前提一位,这样(若是删除的这一项后面还有1000万项,那么这1000万项的索引都要向前提一位)会大大的消耗性能,
- 因此咱们须要作进一步的优化处理;
for (let i = 0; i < arr.length - 1; i++) {
let item = arr[i];
for (let j = i + 1; j < arr.length; j++) {
if (item === arr[j]) {
// 用最后一项替换当前项
arr[j] = arr[arr.length - 1];// 原始数组中的顺序会变化,可是不会致使索引前置这种状况(性能好)
// 最后一项删掉
arr.length--;
// 下一轮还和这一项比(由于这一项已经变为最新的最后一项了)
j--;
}
}
}
console.log(arr);
复制代码
原理:利用对象中属性名不能重复的特色,先创建一个空对象,而后依次循环数组中的每一项,把此项做为obj对象的属性名和属性值,在添加的时候,若是这个属性名对应的值已经存在,说明此项重复,删除掉此项浏览器
let arr = [1, 2, 3, 1, 1, 4, 2, 3];
let obj = {};
for (let i = 0; i < arr.length; i++) {
// 把每一次循环获得的当前项,做为对象的属性名和属性值存储进去
let item = arr[i];
if (obj[item] !== undefined) {
// 证实对象中有这个属性(也就是以前存储过,数组中以前就有这个值),当前值是重复的,咱们须要把当前这项的值删掉便可
arr[i] = arr[arr.length - 1];
arr.length--;
i--;
continue;
}
obj[item] = item;
}
console.log(arr);
复制代码
10
和字符串'10'
,则也会认为是重复的(对象中的属性名是数字和字符串没啥区别);undefined
可能也会出现问题....原理:建立一个新数组,遍历原数组,若是新数组中没有那一项的话,就把它
push
进去性能优化
let arr=[1,2,1,3,3,2,3];
let newAry=[];
/*把原数组中的每一项,只要在新数组中没存在过,咱们就把它放进去,最后newAry就是我们最终要的数组*/
for(let i=0;i<arr.length;i++){
let item=arr[i];
if(newAry.indexOf(item)==-1){
newAry.push(item);
}
}
arr = newAry;
console.log(arr);
复制代码
/* ES6中没有提供现成的去重办法,可是提供了一些去重的方式 :Set数据结构*/
let obj = { y: 200 };
let arr = [obj, 1, 2, 3, 1, obj, 1, 4, 2, 3, '3', { x: 100 }, { x: 100 }];
arr = Array.from(new Set(arr));
console.log(arr);
复制代码