码文不易,转载请带上本文链接,感谢~ https://www.cnblogs.com/echoyya/p/14555831.html

一般的方法此处也不列举了,还是有很多的,如双层循环判断是否相等,或新建数组比较再push等等,需要注意的是,使用splice方法移除元素时,有可能会导致数组塌陷问题,需要处理一下

本文中介绍了多种数组去重的方法,使用了较多的高阶方法及API,并给出相应解释及语法,还有其他多种组合调用方式,原理逻辑其实都差不多,其中for循环可以与forEach方法相互转换,因此此处便不再一一列举,大家如果有更好的算法,可以留言给我,虚心请教!!



给定一个数组 [1,2,2,4,null,null,'3','abc',3,5,4,1,2,2,4,null,null,'3','abc',3,5,4] 去除重复项

let arr =  [1,2,2,4,null,null,'3','abc',3,5,4,1,2,2,4,null,null,'3','abc',3,5,4]

1. 利用对象的 key 唯一

众所周知,对象的key不可重复,否则后者将覆盖前者。利用该特性,实现数组去重,遍历数组,将数组的每一项做为对象的key值

let obj = {};
for (let i = 0; i < arr.length; i++) {
let item = arr[i]
if (obj[item] !== undefined) {
arr.splice(i, 1);
i--; // 解决删除元素后,数组塌陷问题
continue;
}
obj[item] = item
} // arr: [1, 2, 4, null, "3", "abc", 3, 5]

2. 交换元素位置从而替换调 splice方法

上述方法存在一定的性能问题,也就是说,基于splice实现删除性能不太好,当前项被删除后,随后每一项的索引都要向前移动一位,数据量较庞大时,一定会影响性能。

基于以上考虑,交换元素的位置,效率会更高一点,若当前元素重复,则与数组最后一位元素交换位置,i--再次进行判断即可,同时length--,操作数组的长度实现删除数组的最后一个元素,这样便不会影响到数组中其他元素

let obj = {};
for (let i = 0; i < arr.length; i++) {
let item = arr[i]
if (obj[item] !== undefined) {
arr[i] = arr[arr.length-1]
arr.length--;
i--;
continue;
}
obj[item] = item
}
// arr: [1, 2, 4, null, "3", "abc", 3, 5]

3. Array.filter + Array.indexOf

filter() 方法:创建一个新数组,新数组中的元素是指定数组中符合某种条件的所有元素。如果没有符合条件的元素则返回空数组。

语法:array.filter(function(item,index,arr))

filter() 不会对空数组进行检测。

filter() 不会改变原始数组。

原理:返回 item 第一次出现的位置等于当前的index的元素

let newArr = arr.filter((item, index) => arr.indexOf(item) === index);  

// [1, 2, 4, null, "3", "abc", 3, 5]

4. Array.filter + Object.hasOwnProperty

hasOwnProperty() 方法:返回一个布尔值,表示对象自身属性中是否具有指定的属性

原理:利用对象的键名不可重复的特点

let obj = {}

arr.filter(item => obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true))

5. Array.reduce + Array.includes

reduce() 方法:接收一个函数作为累加器,数组中的每个值从左到右开始计算,最终计算为一个值。

语法:arr.reduce(function(total, currValue, currIndex, arr), initValue)

reduce() 对于空数组是不会执行回调函数的。

total:必需。初始值, 或者计算结束后的返回值

currValue:必需。当前元素

currIndex:可选。当前元素的索引

arr :可选。当前数组对象。

initValue:可选。累加器初始值

  • 一个空数组调用reduce()方法且沒有提供初始值会报错
  • 一个空数组调用reduce()方法且提供了初始值,将直接返回该初始值,不會调用 callback 函数。
  • 非空数组调用reduce()提供初始值,则total将会等于初始值,且 currValue从第一个元素开始;若沒有提供初始值,则 total 会等于的第一个元素值,且 currValue将会从第二个元素开始。
let newArr = arr.reduce((accu, cur) => {
return accu.includes(cur) ? accu : accu.concat(cur); // 1. 拼接方法
// return accu.includes(cur) ? accu : [...accu, cur]; // 2. 扩展运算
}, []); // [1, 2, 4, null, "3", "abc", 3, 5]

6. Array.indexOf

indexOf() 方法:返回数组中某个指定的元素位置。该方法遍历数组,查找有无对应元素并返回元素第一次出现的索引,未找到指定元素则返回 -1。

let newArr = []
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) === -1) newArr.push(arr[i])
} //等同于 forEach 写法
arr.forEach( item => newArr.indexOf(item) === -1 ? newArr.push(item) : '') console.log(newArr) // [1, 2, 4, null, "3", "abc", 3, 5]

7. Array.includes

includes() 方法:用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。

let newArr = []
for (var i = 0; i < arr.length; i++) {
if (!newArr.includes(arr[i])) newArr.push(arr[i])
} //等同于 forEach 写法
arr.forEach( item => !newArr.includes(item) ? newArr.push(item) : '') console.log(newArr) // [1, 2, 4, null, "3", "abc", 3, 5]

8. new Set + 扩展运算符 || Array.from

ES6 提供了新的数据结构 Set。类似于数组,但是成员的值都是唯一的,没有重复的值。

Set本身是一个构造函数,可以接受一个具有 iterable 接口数据结构作为参数(如数组,字符串),用来初始化。

let newArr = [...new Set(arr)];      // [1, 2, 4, null, "3", "abc", 3, 5]

let newArr = Array.from(new Set(arr));      // [1, 2, 4, null, "3", "abc", 3, 5]

let newStr = [...new Set('ababbc')].join('')  //  'abc'

9. new Map

ES6 提供了新的数据结构 Map 。类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。

get方法读取key对应的键值,如果找不到key,返回undefined

has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。

let map = new Map();
let newStr = []; for (let i = 0; i < arr.length; i++) {
if (!map.has(arr[i])) {
map.set(arr[i], true);
newStr.push(arr[i]);
}
}
console.log(newArr) // [1, 2, 4, null, "3", "abc", 3, 5]

亲测有效JS中9种数组去重方法的更多相关文章

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

    总结一下JS中用到的数组去重的方法  方法一: 该方法利用对象的属性值不能相同: function arrDelLikeElement (array) { const result = []; con ...

  2. js中几种常见的方法的实例 shift,unshift,push,prop

    1.shift()定义和用法 shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值. 语法:arrayObject.shift() 返回值:数组原来的第一个元素的值. 说明:如果 ...

  3. js中三种全局变量声明方法

    声明方式一: 使用var(关键字)+变量名(标识符)的方式在function外部声明,即为全局变量,否则在function声明的是局部变量.该方式即为显式声明详细如下: <script> ...

  4. js最高效的数组去重方法

    var arr=[1,2,33,2,4,5,33,5,7,8,1,3];var result=[];var temp={};for( var i=0;i<arr.length;i++){ if( ...

  5. js中的伪数组

    一, 伪数组 1. 具有length属性 2. 按索引方式存储数据 3. 不具有数组的方法, 比如push(),pop()等 二, 生成伪数组的方法 在js中生成伪数组的方法比较多 1. functi ...

  6. JavaScript 数组去重 方法汇总

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  7. JS中几种常见的数组算法(前端面试必看)

    JS中几种常见的数组算法 1.将稀疏数组变成不稀疏数组 /** * 稀疏数组 变为 不稀疏数组 * @params array arr 稀疏数组 * @return array 不稀疏的数组 */ f ...

  8. js中对arry数组的各种操作小结

    最近工作比较轻松,于是就花时间从头到尾的对js进行了详细的学习和复习,在看书的过程中,发现自己平时在做项目的过程中有很多地方想得不过全面,写的不够合理,所以说啊,为了在以后的工作中写出最优化的代码,我 ...

  9. js中对arry数组的各种操作小结 瀑布流AJAX无刷新加载数据列表--当页面滚动到Id时再继续加载数据 web前端url传递值 js加密解密 HTML中让表单input等文本框为只读不可编辑的方法 js监听用户的键盘敲击事件,兼容各大主流浏览器 HTML特殊字符

    js中对arry数组的各种操作小结   最近工作比较轻松,于是就花时间从头到尾的对js进行了详细的学习和复习,在看书的过程中,发现自己平时在做项目的过程中有很多地方想得不过全面,写的不够合理,所以说啊 ...

随机推荐

  1. copy-webpack-plugin & ignore folder

    copy-webpack-plugin & ignore folder https://github.com/webpack-contrib/copy-webpack-plugin#ignor ...

  2. DataBase All in One

    DataBase All in One DB SQL: relational database management system NoSQL(Not only SQL / Non SQL): key ...

  3. setTimeout 实现原理, 机制

    setTimeout 实现原理, 机制 JS 执行机制说起 浏览器(或者说 JS 引擎)执行 JS 的机制是基于事件循环. 由于 JS 是单线程,所以同一时间只能执行一个任务,其他任务就得排队,后续任 ...

  4. how to check website offline status in js

    how to check website offline status in js https://developer.mozilla.org/en-US/docs/Web/API/Navigator ...

  5. iOS remote debug & Android remote debug & Chrome & APP

    iOS remote debug & Android remote debug & Chrome & APP iOS remote debugging 如何在 iOS 真机上调 ...

  6. svg click event bug & css pointer-events

    svg click event bug & css pointer-events svg click event not working Error OK ??? css class /* d ...

  7. WebAssembly JavaScript APIs

    WebAssembly JavaScript APIs https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScrip ...

  8. VAST维萨币二月发行,高倍币重现江湖!

    市场长期的历史经验表明,经营盈利能力最好的企业,经常是那些现在的经营方式与5年前甚至10年前几乎完全相同的企业.这个经营模式放到币圈也是一样的,2020年的挖矿是最火的,这个模式现在在市场也同样受用. ...

  9. 大话Spark(6)-源码之SparkContext原理剖析

    SparkContext是整个spark程序通往集群的唯一通道,他是程序的起点,也是程序的终点. 我们的每一个spark个程序都需要先创建SparkContext,接着调用SparkContext的方 ...

  10. tibco EMS 8.2.0安装

    安装环境 序号 项目 值 1 OS版本 Red Hat Enterprise Linux Server release 7.1 (Maipo) 2 内核版本 3.10.0-229.el7.x86_64 ...