JS极限操作之数组去重
简介:
普遍型:
var arr = [1,'4',56,7,332,2,6,4,213,4,7,7,56,2,6];
var res = []; //预定义结果数组
for(var i = 0; i < arr.length; i++){
if(res.indexOf(arr[i]) == -1){ //判断结果数组是否含有该项
res.push(arr[i]); //如果没有,推入结果数组
}
}
console.log(res); // [ 1, '4', 56, 7, 332, 2, 6, 4, 213 ]
以上写法,是最为普遍的,对一个数组for循环进行遍历,没啥问题,不过,JS本身提供了遍历数组的多种方法,而且其中最符合当前写法的就是filter()函数,其中第一个参数为函数,在遍历时,将会将将所有函数返回结果为true的那一项组成一个新的数组返回。
所以……
ES5精简型:
var arr = [1,'4',56,7,332,2,6,4,213,4,7,7,56,2,6];
var res = arr.filter(function(v,i,arr) {
return arr.indexOf(v,i+1) == -1;
});
console.log(res); // [ 1, '4', 332, 213, 4, 7, 56, 2, 6 ]
解释一下参数,三个参数分别代表遍历对象当前的值,下标,当前数组,而遍历的时候,并没有对res进行操作,所以,我们没法复刻上面的思路,思路就应该转变为,当前元素后面还有没有一样的,如果没有了,说明它是最后一个,就可以取出来,indexOf()函数第二个参数即为从哪个下标位置开始找。
可以看到结果的排列方式和上面其实并不一样,因为我们取得方式不一样,不过我们同样达到了目的。
当我们到了ES6的时候,JS再次提供帮助,有了一个includes()方法,同样是查找有没有,参数也一样,但是这个直接可以返回布尔值,那么我们完全可以利用这个函数对我们的代码进行精简,而且,函数的写法也可以精简为ES6的箭头函数,对于直接返回计算结果的函数,连大括号都省了。
来,让我们一行搞定他~
ES6精简型:
var arr = [1,'4',56,7,332,2,6,4,213,4,7,7,56,2,6];
var res = arr.filter((v,i,arr) => !arr.includes(v,i+1));
console.log(res); // [ 1, '4', 332, 213, 4, 7, 56, 2, 6 ]
思路跟上面一样,换了个写法而已,就不多解释了。
ES6 其实还给array新增了一个from方法,以及Set类型,能写的更简单。
ES6极度精简型:
var arr = [1,'4',56,7,332,2,6,4,213,4,7,7,56,2,6];
var res = Array.from(new Set(arr));
console.log(res); // [ 1, '4', 332, 213, 4, 7, 56, 2, 6 ]
Set作为ES6新的类型,相当于一个没有下标的数组,在用一个数组进行生成的时候,其实已经完成了去重,然后我们在通过Array的from方法对他生成新的数组,那么一个崭新的数组就呈现出来了~
你以为这就完了吗?怎么可能!我还有个一行的写法!前方高能!
六亲不认型:
var arr = [1,'4',56,7,332,2,6,4,213,4,7,7,56,2,6];
arr.sort().reduceRight( (p, c, i) => ( c === p && arr.splice( i + 1, 1 )[0] ) || c );
console.log(arr); //[ 1, 2, 213, 332, 4, '4', 56, 6, 7 ]
我写这个思路的时候,就一个想法,别整什么新数组,直接操作原数组,而且还完成了顺手的排序。
这个写法得思路是,先将数组进行排序,不管以任何方式,再乱的一个数组也会达到一个“只有相邻的才会出现相同元素”的数组,那么我们只需要将数组中相同的给删除掉就好。
其次,如果要对原数组进行删除操作,那么从尾部开始遍历是最合适的,因为将数组抽出一个元素将会改变数组的下标,如果从后面遍历,将不会影响前面的所有元素的下标。
接下来,你需要了解的知识是:reduce()函数、逻辑操作符的返回值及短路特性。
reduce()原理:第一个参数为function,执行时会传入四个参数:prev上一个函数执行的返回值(第一次时传入数组第一个值),current当前遍历的值(从第二个开始,到最后),index当前值的下标(从第二个开始,即1开始),array传入当前被遍历的对象。因为prev是由上一次的返回值带来的,所以普遍用来计算数组的总和;
然后解释里面的代码,它效果全等于一下代码:
//源代码:
return (c === p && arr.splice( i + 1, 1 )[0] ) || c ;
//全等于
if(c === p){ // 判断当前值是否与前一个相等
return arr.splice( i + 1, 1 )[0]; // 如果相等则从数组中删除并去除后面的元素
}else{
// 如果c === p 返回false的话,上面整个括号内都是false,效果跟这个差不多
return c;
}
总之,这个写法,优点是,第一,方便的对原数组进行操作,第二,代码将会带着满满的骚气~
One situation is when recurrent dislocations occur. http://genqpviag.com 100 mg generic viagra