数组去重在面试和工作中都是比较容易见到的问题, 这几天在复习基础知识的时候, 也顺便总结了一下常见的方法, 和大家一起分享. 如果大家还有其他什么方法还请评论大家一起讨论. 如果有什么没有表达正确的地方还请大家斧正.
一, 使用双重 for 循环
要比较数组中的每一个值我们都可以用双重 for 循环来解决, 比如冒泡排序. 同样也可以使用双重 for 循环来数组去重.
- function unique(arr) {
- for (let i = 0; i <arr.length; i++) {
- for (let j = i+1; j < arr.length; j++) {
- if (arr[i] == arr[j]) {
- arr.splice(j,1)
- j--
- }
- }
- }
- return arr
- }
- let arr = [1,1,'true','true', 'a', 'a',true,true,false,false, undefined,undefined, null,null, NaN, NaN,'NaN','NaN', 0, 0,{},{},[],[]];
- console.log(unique(arr)) // [ 1, 'true', 'a', false, undefined, NaN, NaN, 'NaN', {}, {} ]
可以看见 NaN 没有被去除掉, 两个 {} 都没去掉, 因为 {} 是引用值, 而却我们使用的是 arr[i] == arr[j]会发生类型转换, 所以以下都为 true:
- 1 == true
- false== []
- undefined == null
- false == 0
要解决以上问题我们可以使用 Object.is(arr[i], arr[j])的方法替换 arr[i]==arr[j]既可以去除 NaN 还可以防止发生类型转换. 代码这里接不贴出了, 大家可以自己写一下运行一下.
注: 为了方便以下 arr 都使用该处的 arr 值
二, 利用 indexOf()
使用 indexOf(), 可以判断一个数组中是否包含某个值, 如果存在则返回该元素在数组中的位置, 如果不存在则返回 - 1.
- functon unique(arr) {
- let res = []
- for (let i = 0; i < arr.length; i++) {
- if (res.indexOf(arr[i]) === -1) {
- res.push(arr[i])
- }
- }
- return res
- }
- console.log(unique(arr)) //[ 1, 'true', 'a', true, false, undefined, null, NaN, NaN, 'NaN', 0, {}, {}, [], []]
这里我们新建一个数组来保存去重后的数组, 如果该数组不包含元素就将该元素 push 到该数组中, 可以发现这种方法任然没有去掉 NaN,{},[].
三, 利用 includes()
使用 includes()方法也可以判断数组是否包含某个特定的元素, 如果包含就返回 true 不包含就返回 false. 这和 indexOf()方法有些类似, 所以我们使用 includes()进行数组去重和 indexOf()的方法原理是一样的.
- functon unique(arr) {
- let res = []
- for (let i = 0; i < arr.length; i++) {
- if (!res.includes(arr[i])) {
- res.push(arr[i])
- }
- }
- return res
- }
四, 利用 filter()
filter() 方法创建一个新的数组, 新数组中的元素是通过检查指定数组中符合条件的所有元素. 并且 filter()不会改变数组, 也不会对空数组进行检测. filter()方法接收一个回调函数.
语法:
array.filter(function(item,index,arr), thisValue)
参数 | 描述 |
---|---|
item | 必须。当前元素的值 |
index | 可选。当前元素的索引值 |
arr | 可选。当前元素属于的数组对象 |
代码实现
- function unique(arr) {
- return arr.filter((item,index, arr) => {
- return arr.indexOf(item) === index
- })
- }
- console.log(unique(arr)) //[ 1, 'true', 'a', true, false, undefined, null, 'NaN', 0, {}, {}, [], [] ]
这里我们用判断 indexOf(item)判断当前元素的索引是否等于当前 index, 如果相等就返回该元素.
五, 使用对象的特点
对象是一种以键值对存储信息的结构, 并且不能有重复的键.
- function unique(arr) {
- let obj = {}
- for (let i = 0; i < arr.length; i++) {
- if (arr[i] in obj) {
- obj[arr[i]] ++
- } else {
- obj[arr[i]] = 10
- }
- }
- return Object.keys(obj) // 以数组的形式返回键
- }
- console.log(unique(arr)) // [ '0', '1', 'true', 'a', 'false', 'undefined', 'null', 'NaN', '[object Object]', '']
这种方法的写出来有点问题, 因为是用 Object.keys(obj)来返回键的集合所以得到的都是字符串的形式.
六, 使用 set
ES6 提供了新的数据结构 Set. 它类似于数组, 但是成员的值都是唯一的, 没有重复的值.
- function unique(arr) {
- return [...new Set(arr)]
- }
- console.log(unique(arr)) //[ 1, 'true', 'a', true, false, undefined, null, NaN, 'NaN', 0, {}, {}, [], [] ]
这是 ES6 最常用的方法, 得到的效果也还不错.
谢谢你的阅读. 希望大家也可以把自己常用的方法分享一起交流.
来源: https://juejin.im/post/5c7e0328f265da2dc538da03