本人菜鸡,前两天去面试,发现再次碰到数组去重这道面试题,比较常见。能够达到去重效果的方法有好几个,感觉有必要整理一下其中几种常见实现:
1,思路:创建一个空数组,然后循环需要去重的数组,对比创建的数组,如果新创建的数组中不存在当前循环下标值的时候就将它push到新数组中,否则执行下次循环,
代码如下:
Array.prototype.distinct = function(){
//创建一个空数组,专门存放循环时去重数组中每个第一次出现的元素
var resArr = [];
for( var i = 0 ; i < this.length ; i ++ ){
//判断数组resArr中是否存在当前循环数组中元素
resArr.indexOf(this[i]) === -1?resArr.push( this [ i ] ):'';
}
return resArr;
}
2,思路:还是循环需要去重的数组(后面简称oldArr),每次循环oldArr时其中再套一个循环,看外层循环数组的元素在内层循环中是否有再次出现(这个时候
内层循环的起始值为外层循环的下一个元素下标),如果有再次出现则需要将外层循环下标向前移动一位,且内层循环任然置为外层循环当前下标的
前一位。如果没有再次出现的话,则表示当前外层循环的元素下标为数组中出现的最后一个相同元素,让后将它放到一个数组里面,就这样循环玩整
个oldArr,将上述的值依次push到数组里面,然后返回。
代码如下:
Array.prototype.dupRem = function(){
//存放结果的空数组
var resArr = [];
for(var i=0;i<this.length;i++){
for(var j=i+1;j<this.length;j++){
//当外层循环的当前元素在其后面存在相同元素时,外层循环体下标加1
if(this[i] === this[j]){
j = ++i;
}
}
//将在后续中没有出现的元素放入结果集数组中
resArr.push(this[i]);
}
return resArr;
}
3,思路:这个方法其实与上面的方法方式类似 ,上一个是结果返回一个新数组,不会改变原数组。
代码如下:
Array.prototype.dupRem = function(){
//将操作数组长度保存在一个变量里面
var len = this.length;
//外层循环数组
for(var i = 0;i<len;i++){
//内层循环
for(var j = i+1;j<len;j++){
//同样,当在内层循环中(即在当前数组元素的后面出现相同元素)出现相同元素时,删除该元素
if(this[i] === this[j]){
this,splice(j,1); //删除后面的相同元素
len --; //元素删除后,标识数组长度的len也跟随着减1
j --; //元素删除后,为保证循环完整,内层循环下标减1,
}
}
}
return this; //返回去重处理过后的原数组
}
毛病:占内层,速度慢。
4,思路:利用对象属性不能重复的特性去重。新建一个空对象,将数组元素作为对象键名放入新建的空对象中,每次对象添加新属性时就将属性名push 到一个
数组里面,最后返回这个数字,结果即为去重后的数组
代码如下:
Array.prototype.dupRem = function(){
var len = this.length, //将数组元素保存起来
arr = [], //存放结果的数组
obj = {}; //用于判断重复性的对象
for(var i = 0;i<len;i++){
//判断对象中是否存在以当前循环下标为键名的属性,不存在的时候即为第一次出现(后续对比中出现相同元素的时候忽略)
if(!obj[this[i]]){
obj[this[i]] = '任意值';
arr.push = this[i];
}
}
//返回去重后的结果数组
return arr;
}
5,使用ES6的set数据结构:
function dopRem(arr){
return Array.from(new Set(arr));
}