js数组去重的几种方式

数组去重的多种实现方法解析
本文详细介绍了数组去重的几种常见方法,包括普通遍历、使用对象哈希、排序对比、ES6 Set 和 Map 去重。针对不同情况,如基本类型与对象类型的数据,各种方法有不同的优缺点。例如,Set 方法简洁但无法处理对象去重,而Map方法可以区分数据类型但无法去除相同对象。最后,提供了每种方法的示例代码以供参考。

数组去重

数组去重是一个很常见的需求,而实现的方式也多种多样,接下来我们来看看有哪些实现方式。

一、普通方法

创建一个空数组 `arr`,遍历原始数组(this)的每一项,如果当前项不存在 `arr` 中,则 `push` 进 `arr`

缺点:这里其实是两层遍历。第一层是外层的 `for` 循环,第二层是内部的 `indexOf` 判断


Array.prototype.unique = function() {
  var arr = [];
  var len = this.length;
  for(var i=0; i<len; i++) {
    if(arr.indexOf(this[i]) === -1) arr.push(this[i]);
  }
  return arr;
}

二、较快的方式

使用对象(hash)的方式来记录是否已经存在


Array.prototype.unique = function() {
  var json = {};
  var arr = [];
  var len = this.length;
  for(var i=0; i<len; i++) {
    if(typeof json[this[i]] === "undefined") {
      json[this[i]] = true;
      arr.push(this[i]);
    }
  }
  return arr;
}

但是有时我们会发现上述方法失灵了,例如数组:`[1, "1", 2, 2]`

我们希望去重之后得到的结果是:`[1, "1", 2]`,但是会发现结果变成了 `[1, 2]`

这其实是因为我们在使用 `hash` 的时候,就是把数组元素作为 `hash` 的 `key` 值了,那么在使用过程中就会把**数组元素变成字符串**。

-   解决方案:使用 `Object.prototype.toString.call`

可以具体判断出 `key` 的数据类型


json[this[i]] = {}; // json[1] = {}
// json[1]["[object Number]"] = 1
// json[1]["[object String]"] = 1
json[this[i]][Object.prototype.toString.call(this[i])] = 1; 

`json` 中的每一项,也都是一个对象。内部对象的 `key` 值为当前循环项的类型,外部对象(`json`)的 `key` 值为当前循环项的**字符串内容**

例如:`[1, "1"]`,在 `json` 的存储中就会变为
json = {
  1: {
    "[object Number]": 1, // value赋值为1,就可以统计重复的数量了,具有更好的扩展性
    "[object String]": 1
  }
}
Array.prototype.unique = function() {
  var json = {}, arr = [], len = this.length;
  for(let i=0; i<len; i++) {
    var type = Object.prototype.toString.call(this[i]); // 类型
    if(typeof json[this[i]] === "undefined") { // 如果json[1]为undefined,则对其初始化
      json[this[i]] = {}; // 初始化为空对象
      json[this[i]][type] = 1; // json[1]["[object Number]"] = 1,记录为1
      arr.push(this[i]); // 在新数组中添加当前项
    } else if(json[this[i]][type] === "undefined") { // json层的对象已经初始化过了,但内部type为key的内容还没记录过
      // 类似于:json[1]["[object Number]"]有值,但json[1]["[object String]"]未定义
      json[this[i]][type] = 1;
      arr.push(this[i]);
    } else { // 剩下的就是定义过的,直接+1就行了
      json[this[i]][type]++;
    }
  }
}

缺点:不能为对象去重。如果传入的数组为 `[{ a: 1 }, {}]`,则去重的结果就是 `[{ a: 1 }]`,因为对象转为字符串后都是 `[object Object]`

 三、排序后对比

-   先对数组进行排序:可以让相同的数据挨在一起

-   定义一个新的空数组

-   遍历排序后的数组

    -   如果当前项等于新数组的最后一项,则跳过
    -   如果不等于,则将当前项插入新数组
Array.prototype.unique = function() {
  this.sort(); // 先排序
  var arr = [], len = this.length;
  for(var i=0; i<len; i++) {
    if(this[i] !== arr[arr.length - 1]) { // 如果当前项不等于arr的最后一项
      arr.push(this[i])
    }
  }
  return arr
}
 

 四、利用ES6的Set


function unique(arr) {
  return [...new Set(arr)];
}
 

不考虑兼容性的话,这种去重的方法代码量最少。


const arr = [1, "1", {}, {}];
console.log(unique(arr)); // [ 1, '1', {}, {} ]
 

通过上述代码的打印结果,可以看出 `new Set` 的方法可以区分出数据类型,但是无法去掉相同对象。(本质上是因为对象都是引用)

 五、利用Map去重


function unique(arr) {
  const map = new Map();
  const array = [];
  for (let i = 0; i < arr.length; i++) {
    if (map.has(arr[i])) { // 如果已经存在了,则将其值设为 true(说明是重复元素)
      map.set(arr[i], true);
    } else { // 否则将其值设为false(目前没重复)
      map.set(arr[i], false);
      array.push(arr[i]);
    }
  }
  return array;
}

### 回答1: 有以下几种方法可以对JavaScript数组进行: 1. 使用 Set 数据结构: ```javascript let arr = [1, 2, 2, 3, 3, 4]; let uniqueArr = [...new Set(arr)]; console.log(uniqueArr); // [1, 2, 3, 4] ``` 2. 使用 filter() 方法: ```javascript let arr = [1, 2, 2, 3, 3, 4]; let uniqueArr = arr.filter((item, index, array) => { return array.indexOf(item) === index; }); console.log(uniqueArr); // [1, 2, 3, 4] ``` 3. 使用 reduce() 方法: ```javascript let arr = [1, 2, 2, 3, 3, 4]; let uniqueArr = arr.reduce((prev, cur) => { if (prev.indexOf(cur) === -1) { prev.push(cur); } return prev; }, []); console.log(uniqueArr); // [1, 2, 3, 4] ``` 4. 使用 Map 数据结构: ```javascript let arr = [1, 2, 2, 3, 3, 4]; let map = new Map(); let uniqueArr = []; arr.forEach(item => { if (!map.has(item)) { map.set(item, true); uniqueArr.push(item); } }); console.log(uniqueArr); // [1, 2, 3, 4] ``` 这些方法中,使用 Set 数据结构的方法最简单,代码最短。 ### 回答2: JS数组几种方法有以下几种: 1. 使用Set:将数组转换为Set,Set中的元素是唯一的,然后将Set转换回数组。例如: ```javascript var arr = [1, 2, 3, 3, 4, 4, 5]; var uniqueArr = Array.from(new Set(arr)); console.log(uniqueArr); // [1, 2, 3, 4, 5] ``` 2. 使用indexOf:遍历数组,使用indexOf方法判断元素在新数组中是否存在,如果不存在则将元素添加到新数组中。例如: ```javascript var arr = [1, 2, 3, 3, 4, 4, 5]; var uniqueArr = []; for (var i = 0; i < arr.length; i++) { if (uniqueArr.indexOf(arr[i]) === -1) { uniqueArr.push(arr[i]); } } console.log(uniqueArr); // [1, 2, 3, 4, 5] ``` 3. 使用includes:遍历数组,使用includes方法判断元素在新数组中是否存在,如果不存在则将元素添加到新数组中。例如: ```javascript var arr = [1, 2, 3, 3, 4, 4, 5]; var uniqueArr = []; for (var i = 0; i < arr.length; i++) { if (!uniqueArr.includes(arr[i])) { uniqueArr.push(arr[i]); } } console.log(uniqueArr); // [1, 2, 3, 4, 5] ``` 以上是常见的几种JS数组的方法,具体选择哪种方法可以根据实际需求和性能要求进行选择。 ### 回答3: 在JavaScript中,数组有多种方法: 1. 使用Set:Set是ES6中的新数据类型,它只能存储唯一的值。我们可以将数组转换成Set,然后再将Set转换回数组即可实现。 ```javascript let arr = [1, 2, 3, 3, 4, 4, 5]; let uniqueArr = [...new Set(arr)]; console.log(uniqueArr); // [1, 2, 3, 4, 5] ``` 2. 使用filter方法:通过使用filter方法遍历数组,返回一个新数组,只保留第一次遇到的元素。 ```javascript let arr = [1, 2, 3, 3, 4, 4, 5]; let uniqueArr = arr.filter((item, index, array) => { return array.indexOf(item) === index; }); console.log(uniqueArr); // [1, 2, 3, 4, 5] ``` 3. 使用reduce方法:通过使用reduce方法遍历数组,返回一个新数组,只保留第一次遇到的元素。 ```javascript let arr = [1, 2, 3, 3, 4, 4, 5]; let uniqueArr = arr.reduce((prev, curr) => { if (prev.indexOf(curr) === -1) { prev.push(curr); } return prev; }, []); console.log(uniqueArr); // [1, 2, 3, 4, 5] ``` 以上是JS数组几种常见方法,可以根据具体情况选择合适的方法进行使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值