数组去重

数组去重

整理下数组去重的几种方法.

第一种

先将数组排序,变量 result 存储结果数组,将原数组的每一项与结果数组的最后一项比较,如果不相等,则将其 push 进 result 数组。

缺点,数组最终结果是有序的。如果不想要有序的结果,则采用二、三、四的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var testArray = [6,6,3,4,5,1,7,4,1,2]

Array.prototype.unique1 = function() {
this.sort((a,b) => a-b);
var result = [];

this.forEach((e, idx) => {
if(idx === 0) {
result.push(e)
}

if(e !== result[result.length-1]) {
result.push(e)
}
})

return result;
}

//更加简便的写法.思路是一样的
Array.prototype.unique2 = function() {

return this.sort((a,b) => a-b).reduce((result, e) => {
if(result.length === 0 || e !== result[result.length-1]) {
result.push(e)
}
return result;
}, [])
}

可以利用数组的 reduce 方法来简写代码.

第二种

ES6。 只需要用一行代码. 很简洁.
Set本身是一个构造函数,可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数来初始化.

主要是利用的Set这个新的数据结构的特性,就是其内部成员的值都是唯一的,没有重复.
还有就是Set数据结构本身具有Iterator接口,说明Set数据结构是可遍历的.

ES6 的扩展运算符...可以将实现了Iterator接口的对象,转化为真正的数组

1
var result = [...new Set(testArray)];

第三种

利用 indexOf()方法,返回在数组中找到第一个给定元素的索引值,如果没找到,则返回-1

1
2
3
4
5
6
7
8
9
10
11
Array.prototype.unique3 = function() {
var result = [];

this.forEach((e, idx) => {
if(result.length === 0 || result.indexOf(e) === -1) {
result.push(e)
}
})

return result;
}

内部利用 Array.prototype 的 indexOf()方法,对待去重数组里的每一个元素,在 result 数组中寻找第一次出现的索引值,如果为-1,则说明该元素没有在 result 数组里,则将其添加到 result 数组里.

第四种

利用一个空对象来比较,用一个循环来遍历数组,每遍历到一个元素,就用这个元素作为 key 去对象中访问,如果访问得到的话,就说明重复了,反之,则把该元素加入到 result 数组中,并将此元素作为对象的属性,赋值为 1。
这种办法虽然也是只用到了一次循环,可它也有局限性.

1
2
3
4
5
6
7
8
9
10
11
12
Array.prototype.unique4 = function() {
var obj = {},
result = []
for (let i = 0; i < this.length; i++) {
if (!obj[this[i]]) {
result.push(this[i])
obj[this[i]] = 1
}
}
console.log(obj)
return result
}

如果测试数组的格式为[1, 2, 3, ‘1’, ‘2’, ‘3’],如果我们想要的最终结果是[1, 2, 3, ‘1’, ‘2’, ‘3’],使用第四种办法得出的结果只会是[1, 2, 3]. 之所以出现这种情况,是因为 JavaScript 的对象的键类型只能为字符串.

一个对象的属性名可以是任何有效的 JavaScript 字符串,或者可以被转换为字符串的任何类型,包括空字符串. —-MDN

可以看到,后面的属性 1,覆盖了前面的属性”1”,temp现在其实只有两个属性,"""1".遍历对象的 key,输出每个 key 的类型,发现都是 string.说明就算是数字类型的键,JS 内部还会把它转换成字符串.

所以这种方法其实并不是很适用于一个既有数字又有字符串的数组.因为很可能会出现上面的情况.这也是这种方法的局限性.

第五种

利用两个循环来比较,这个效率没上面的其他实现方法高,这里就不写了.