如何返回一个数组中的重复元素?

这个问题好像等同于:如何返回一个数组中被删除的重复元素?
我们换个测试案例,立刻就能看出问题所在。

Array.prototype.distinct = function() {
var ret = [];
for (var i = 0; i < this.length; i++) {
for (var j = i+1; j < this.length; j++) {
if (this[i] === this[j]) {
ret.push(this.splice(j, 1)[0]);
//注意:this.splice(j,1)返回的是一个数组,这个数组只有一个元素
}
}
}
}
//
//for test
console.log(['a','b','a','d','b','a','e'].distinct()); //['a','a','b']

居然返回了两个a,问题出在哪里呢?
第1个a和第二个a比较后,相同,所以把第二个a放入新数组,
当第1个a和第三个a比较后,也相同,所以把第三个a也放入新数组。
所以你看到了返回结果里有两个a。
我们来看下原来的数组和返回的数组有什么不同?

//for test
var arr=['a','b','a','d','b','a','e'];
console.log(arr.distinct()); //["a", "a", "b"]
console.log(arr); //["a", "b", "d", "e"]

也就是说原来的数组里面的重复元素已经去除了,但返回的数组里面包含有重复元素。
也就说放入元素到新数组前必须要先判断下,数组是否已经包含有此元素。
代码改进后如下:

Array.prototype.distinct=function () {
var ret = [];
for (var i = 0; i < this.length; i++) {
for (var j = i+1; j < this.length;j++) {
if (this[i] == this[j]) {
var value=this.splice(j, 1)[0];
if(ret.indexOf(value)==-1){
ret.push(value);
}
}
}
}
return ret;
}
//for test
var arr=['a','b','a','d','b','a','e'];
console.log(arr.distinct()); //["a", "b"] 正确
console.log(arr); //["a", "b", "d", "e"] 正确

如何去掉一个数组中的重复元素?

基于上面的代码:如何返回一个数组中的重复元素,我们可以快速写出:

Array.prototype.uniq=function () {
var ret = [];
for (var i = 0; i < this.length; i++) {
for (var j = i+1; j < this.length;j++) {
if (this[i] == this[j]) {
this.splice(j, 1);
}
}
}
return this;
}
//for test
var arr=['a','b','a','d','b','a','e'];
console.log(arr.uniq()); //["a", "b", "d", "e"] 正确

双重for循环在数据量大时会有性能问题,有没有一种简便的方法呢?
回到我们前面的代码:如何返回一个数组中的重复元素。
为了规避返回的数组中有重复元素,我们做了一个判断。
我们都知道object的key是唯一的。
举例:

var obj={name:'huluoyang',name:'google'};
console.log(obj); //{name:'google'}

所以我们可以利用object的key是唯一的特性,
把数组的元素作为object的key保存起来,这样重复元素就自动被干掉了。
代码如下:

Array.prototype.uniq=function(){
var temp=[];
var obj={};
for(var i=0;i<this.length;i++){
obj[this[i]]=true; //此处的true可以为任何值,仅用来构建一个对象而已。
}
for(i of obj){
temp.push(i);
}
return temp;
}
var arr=['a','b','a','d','b','a','e'];
console.log(arr.uniq());

实现原理:数组和对象的双向转化
怎么样,是不是觉得js很好玩啊,字符串是对象,数组也是对象,object还是对象。
如果你熟悉这些对象之间的不同,你就可以自由穿梭于代码世界,逢山开路,遇水搭桥。