js数组去重是平时我们经常遇见的问题,也是前端面试中比较受面试官青睐的一个算法问题,现将几种方法整理如下:
1.遍历数组法
最简单的去重方法,实现思路:新建一新数组,遍历传入数组,值不在新数组就加入该新数组中;注意点:判断值是否在数组的方法“indexOf”是ECMAScript5 方法,IE8以下不支持,需多写一些兼容低版本浏览器代码,源码如下:
var unique = function(arr){
var result = [];
for(var i = 0; i < arr.length; i++){
if(result.indexOf(arr[i]) == -1) result.push(arr[i]);
}
return result;
}
2、利用Set
ES6 部署了 Set 以及 Array.from 方法,太强大了!如果浏览器支持,完全可以这样:将数组遍历一遍,然后将其每个元素放进set里,利用Set 结构不会添加重复的值这条性质进行去重,最后将Set遍历一遍放到一个数组里。但是这种犯法占用的内存比较大。
var unique = function(arr){
return Array.from(new Set(arr));
}
var unique = function(arr){
return [...new Set(array)];
}
3、排序后相邻去除法
虽然原生数组的”sort”方法排序结果不怎么靠谱,但在不注重顺序的去重里该缺点毫无影响。实现思路:给传入数组排序,排序后相同值相邻,然后遍历时新数组只加入不与前一值重复的值。
var unique = function(arr){
arr.sort();
var result = [arr[0]];
for(var i = 1; i < arr.length; i++){
if(arr[i] != result[result.length-1]) result.push(arr[i]);
}
return result;
}
4、优化遍历数组法
该方法的实现代码相当酷炫,实现思路:获取没重复的最右一值放入新数组。(检测到有重复值时终止当前循环同时进入顶层循环的下一轮判断)推荐
// 思路:获取没重复的最右一值放入新数组
var unique = function(arr){
var result = [];
var len = arr.length;
for(var i = 0; i < len; i++) {
for(var j = i + 1; j < len; j++)
if (arr[i] === arr[j]) j = ++i;
result.push(arr[i]);
}
return result;
}
5、原始写法
最后我们再来看下最原始的写法,如果不借助任何方法,初级写法应该是:
function unique(arr){
var res=[];
for(var i=0;i<arr.length;i++){
var obj = arr[i];
for(var j=0;j<res.length;j++){
if(res[j]===obj) break;
}
if(res.length===j)res.push(obj);
}
return res;
}
判断浏览器是否支持indexOf ,indexOf 为ecmaScript5新方法 IE8以下(包括IE8, IE8只支持部分ecma5)不支持
if (!Array.prototype.indexOf){
// 新增indexOf方法
Array.prototype.indexOf = function(item){
var result = -1, a_item = null;
if (this.length == 0){
return result;
}
for(var i = 0, len = this.length; i < len; i++){
a_item = this[i];
if (a_item === item){
result = i;
return result;
}
}
}
}
6、利用hash表
Array.prototype.unique2 = function()
{
var n = {},r=[]; //n为hash表,r为临时数组
for(var i = 0; i < this.length; i++) //遍历当前数组
{
if (!n[this[i]]) //如果hash表中没有当前项
{
n[this[i]] = true; //存入hash表
r.push(this[i]); //把当前数组的当前项push到临时数组里面
}
}
return r;
}
//用的是hash表。把已经出现过的通过下标的形式存入一个object内。下标的引用要比用indexOf搜索数组快的多。方法远远快于其他两种方法。 但是内存占用方面应该方法比较多,因为多了一个hash表。这就是所谓的空间换时间。