js数组去重的方法

1.如果不借助任何方法,初级写法应该是:

function unique(arr){
    var res=[];
    for(var i=0,len=arr.length;i<len;i++){
        var obj = arr[i];
        for(var j=0,jlen = res.length;j<jlen;j++){
            if(res[j]===obj) break;
        }
        if(jlen===j)res.push(obj);
    }
    return res;
}
var arr=[1,1,‘2‘,‘1‘,3,4]
arr = unique(arr);
console.log(arr);

2.如果不考虑兼容性,会用ES5里面数组的indexOf()方法。

function unique(arr){
    var res =[];
    for(var i=0,len=arr.length;i<len;i++){
        var obj = arr[i];
        if(res.indexOf(obj)===-1) res.push(obj);
    }
    return res;
}
var arr=[1,1,‘2‘,‘1‘,3,4]
arr = unique(arr);
console.log(arr);// arr=[1,‘2‘,‘1‘,3,4]

3.利用ES5数组里的filter过滤:

function unique(a) {

  var res = a.filter(function(item, index, array) {
    return array.indexOf(item) === index;
  });

  return res;
}

var a = [1, 1, ‘1‘, ‘2‘, 1];
var ans = unique(a);
console.log(ans); 

方法二

法一是将原数组中的元素和结果数组中的元素一一比较,我们可以换个思路,将原数组中重复元素的最后一个元素放入结果数组中。

function unique(a) {

var res = [];

for (var i = 0, len = a.length; i < len; i++) {

for (var j = i + 1; j < len; j++) {

// 这一步十分巧妙

// 如果发现相同元素

// 则 i 自增进入下一个循环比较

if (a[i] === a[j])

j = ++i;

}

res.push(a[i]);

}

return res;

}

var a = [1, 1, ‘1‘, ‘2‘, 1];

var ans = unique(a);

console.log(ans); // => ["1", "2", 1]

虽然复杂度还是 O(n^2),但是可以看到结果不同,1 出现在了数组最后面,因为结果数组取的是元素最后一次出现的位置。

方法三(sort)

如果笔试面试时只答出了上面这样 O(n^2) 的方案,可能还不能使面试官满意,下面就来说几种进阶方案。

将数组用 sort 排序后,理论上相同的元素会被放在相邻的位置,那么比较前后位置的元素就可以了。

function unique(a) {

return a.concat().sort().filter(function(item, pos, ary) {

return !pos || item != ary[pos - 1];

});

}

var a = [1, 1, 3, 2, 1, 2, 4];

var ans = unique(a);

console.log(ans); // => [1, 2, 3, 4]

但是问题又来了,1 和 "1" 会被排在一起,不同的 Object 会被排在一起,因为它们 toString() 的结果相同,所以会出现这样的错误:

var a = [1, 1, 3, 2, 1, 2, 4, ‘1‘];

var ans = unique(a);

console.log(ans); // => [1, 2, 3, 4]

当然你完全可以针对数组中可能出现的不同类型,来写这个比较函数。不过这似乎有点麻烦。

方法四 (object)

用 JavaScript 中的 Object 对象来当做哈希表,这也是几年前笔试时的解法,跟 sort 一样,可以去重完全由 Number 基本类型组成的数组。

function unique(a) {

var seen = {};

return a.filter(function(item) {

return seen.hasOwnProperty(item) ? false : (seen[item] = true);

});

}

var a = [1, 1, 3, 2, 1, 2, 4];

var ans = unique(a);

console.log(ans); // => [1, 3, 2, 4]

还是和方法三一样的问题,因为 Object 的 key 值都是 String 类型,所以对于 1 和 "1" 无法分别,我们可以稍微改进下,将类型也存入 key 中。

function unique(a) {

var ret = [];

var hash = {};

for (var i = 0, len = a.length; i < len; i++) {

var item = a[i];

var key = typeof(item) + item;

if (hash[key] !== 1) {

ret.push(item);

hash[key] = 1;

}

}

return ret;

}

var a = [1, 1, 3, 2, ‘4‘, 1, 2, 4, ‘1‘];

var ans = unique(a);

console.log(ans); // => [1, 3, 2, "4", 4, "1"]

虽然解决了讨厌的 1 和 "1" 的问题,但是还有别的问题!

var a = [{name: "hanzichi"}, {age: 30}, new String(1), new Number(1)];

var ans = unique(a);

console.log(ans); // => [Object, String]

但是如果数组元素全部是基础类型的 Number 值,键值对法应该是最高效的!

方法五 (ES6)

ES6 部署了 Set 以及 Array.from 方法,太强大了!如果浏览器支持,完全可以这样:

function unique(a) {

return Array.from(new Set(a));

}

var a = [{name: "hanzichi"}, {age: 30}, new String(1), new Number(1)];

var ans = unique(a);

console.log(ans); // => [Object, Object, String, Number]

_.unique

最后来看看 underscore 对此的实现方式,underscore 将此封装到了 _.unique 方法中,调用方式为 _.unique(array, [isSorted], [iteratee])。其中第一个参数是必须的,是需要去重的数组,第二个参数可选,如果数组有序,则可以传入布尔值 true,第三个参数可选,如果需要对数组迭代的结果去重,则可以传入一个迭代函数。而数组元素去重是基于 === 运算符的。

其实很简单,underscore 中的实现方式和上面的方法一相似。

我们来看它的核心代码:

for (var i = 0, length = getLength(array); i  length; i++) {

var value = array[i],

// 如果指定了迭代函数

// 则对数组每一个元素进行迭代

computed = iteratee ? iteratee(value, i, array) : value;

// 如果是有序数组,则当前元素只需跟上一个元素对比即可

// 用 seen 变量保存上一个元素

if (isSorted) {

// 如果 i === 0,则直接 push

// 否则比较当前元素是否和前一个元素相等

if (!i || seen !== computed) result.push(value);

// seen 保存当前元素,供下一次对比

seen = computed;

} else if (iteratee) {

// 如果 seen[] 中没有 computed 这个元素值

if (!_.contains(seen, computed)) {

seen.push(computed);

result.push(value);

}

} else if (!_.contains(result, value)) {

// 如果不用经过迭代函数计算,也就不用 seen[] 变量了

result.push(value);

}

}

外面的循环遍历数组元素,对于每个元素,如果数组有序,则和前一个元素比较,如果相同,则已经出现过,不加入到结果数组中,否则则加入。而如果有迭代函数,则计算传入迭代函数后的值,对值去重,调用 .contains 方法,而该方法的核心就是调用 .indexOf 方法,和我们上面说的方法一异曲同工。

关于 _.unique 方法的详细代码,可以参考 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L519-L547

时间: 2024-10-25 10:16:23

js数组去重的方法的相关文章

js 数组去重的方法总结

想沉淀一下自己.代码改变世界~~~ 1.利用Array.from代码如下 1 var arr = [1,2,3,4,3,2,1] 2 function unique(arr){ 3 return Array.from(new Set(arr)) 4 } 5 console.log(unique(arr)) 2.利用es6(...)拓展运算符.demo 1 var arr = [1,2,3,4,3,2,1] 2 function unique(arr){ 3 return [...new Set(

JS数组去重 ES6 方法

let arr = [0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 2, 3, 3, 3, 9, 8, 9]; //数组去重法1 console.log(Array.from(new Set(arr))); //数组去重法2 console.log(...new Set(arr)); //数组去重法3 let newarr = []; for (var i = 0; i < arr.length; i++) { if (newarr.indexOf(arr[i]) == -1) {

两种js数组去重的方法

方法一: 新建一个数组,遍历原数组,在新数组内用IndexOf查找原数组内的每一项,如果没有找到,则添加到其中 代码如下: function arrayNew(arrs ){ var newArray = []; for(var i=0;i<arrs.length;i++){ if(newArray.indexOf){ if(newArray.indexOf(arrs[i])==-1){newArray.push(arrs[i])} } else{ if(indexOf(arrs[i],newA

js数组去重的4种方法

js数组去重,老生长谈,今天对其进行一番归纳,总结出来4种方法 贴入代码前 ,先对浏览器Array对象进行支持indexOf和forEach的polyfill Array.prototype.indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, j = this.length; i < j; i++) { if (this[i] === item) { return i; } } return -1; } Ar

js数组去重的三个方法

在工作上,对json数据处理时,例如遇到对某些产品的尺码进行排序,不同的产品都有相同的尺码那是正常不过的事情,如果我们要把这些转成表格的形式来展现,那么这些尺码就不要不能重复才行.在这里呢,我就写几个数组去重的方法,给大家参考参考: 方法一:对数组进行先排序,排完序之后在让元素与前一个元素做对比,相同的就去掉 说明:该方法用到的是sort()方法和slice(),下面我直接贴代码上来,里面有注释说明,相信大家肯定是看得懂的 var arr = ['a', 'b', 'c', 'd', 'e',

JS数组去重的几种常见方法

JS数组去重的几种常见方法 一.简单的去重方法 // 最简单数组去重法 /* * 新建一新数组,遍历传入数组,值不在新数组就push进该新数组中 * IE8以下不支持数组的indexOf方法 * */ function uniq(array){ var temp = []; //一个新的临时数组 for(var i = 0; i < array.length; i++){ if(temp.indexOf(array[i]) == -1){ temp.push(array[i]); } } ret

js 数组去重(数组元素是对象的情况)

js数组去重有经典的 几种方法 但当数组元素是对象时,就不能简单地比较了,需要以某种方式遍历各值再判断是否已出现. 因为: 1.如果是哈希判断法,对象作哈希表的下标,就会自动转换成字符型类型,从而导致所有元素都相等,这时判断方法不再有意义.一般最后数组就只剩一个 2.如果是直接比较法,则因为对象在内存中是按引用访问的,属性值相同的对象也不会相等,简单的直接判断不再有意义.一般最后数组还是原样 所以就需要进行值的比较 当然了,也可以换着法来将相应对象转为字符串(不是默认的那种[object Obj

JS数组去重,js中数组(Array)的排序(sort)

JS数组去重 var ddd = [1,2,4,5,2, 222,1,5,6]; var uq = {}; var rq = []; for(var i=0; i<9; i++){ if(!uq[ddd[i]]){ uq[ddd[i]] = true; rq.push(ddd[i]); } } return rq; js中数组(Array)的排序(sort)注意事项 var arrDemo = new Array(); arrDemo[0] = 10; arrDemo[1] = 50; arrD

js数组去重常用方法

js数组去重是面试中经常会碰到的问题,无论是前端还是node.js数组常见的有两种形式,一种是数组各元素均为基本数据类型,常见的为数组字符串格式,形如['a','b','c'];一种是数组各元素不定,元素中既有基本数据类型,也有引用数据类型,形式如[{name:1,age:2}];这里介绍两种常见的js去重方式. 方法一:针对数组字符串形式(利用set) let arr = [1,2,3,4,5,4,3,2,1]; let set = new Set(); arr.forEach((item)=