set 去重

简介: set 去重

image.png
额~,看样子 set 仅仅对原始类型进行了去重,其实 set 去重的核心逻辑是通过===来判断的

因此 set 只能对原始类型进行去重

两个引用类型是否相等,首先就是判断引用地址是否相等
实现
方法一
其实实现去重也很容易想到,既然引用类型一定地址不同,那么我就将其转换成字符串,也就是 JSON 格式,然后 set 去重,最后转回来
image.png
方法二
那就换个思路去重,自己写个函数,遍历数组,遍历的过程中维护一个 res 数组,如果 res 数组中不存在当前项,那就 push 进去,若存在则跳过
image.png
for 循环用的 for of 因为数组具有迭代器属性,一般数组遍历用这个方法更多。如果发现了当前项和 res 中的某一项是相同的,那么 res 后面的数据就没有必要再进行遍历了,因此终止掉 res 的 for 循环即可,这里用 break,若用 return 就是终止掉了所有的 for 循环了

continue 是终止当前一次的 for 循环,跳到下一次 for 循环

什么时候 push 呢,一定不是 else,因为判断唯一一定是需要让 resItem 全部遍历完保证每一项都不同才能 push,因此这个 push 写在第二层 for 循环的外面
但是直接写在外面又有个缺陷,就是里面的 break 终止了 for 循环,外面的 push 依旧会执行
既然这样那我就搞一个开关变量 isFind 放在第一层 for 循环中,如果 equal 了,那么就将这个 isFind 置为 true,然后 push 就写在当 isFind 为 false 时的判断中
image.png
好,现在来实现辅助函数,判断只要长得一样就是相等,尤其是引用类型,在 v8 看来,地址不同就是不同
equal 实现起来也很简单,真要判断引用类型就一定是双方都是引用类型,如果都不是引用类型或者只有一方是引用类型就是直接判断即可
javascript复制代码function equal(v1, v2) {
if ((typeof v1 === 'object' && v1 !== null) && (typeof v2 === 'object' && v2 !== null)) { // 都是引用类型

} else { // 都不是引用类型、一方是引用类型
    return v1 === v2
}

}

如果双方都是对象,那就需要去判断二者的 key-value 是否都能一一对的上
如果 v1 具有的 key,v2 也具有,那就去看 value,这里用 v2.hasOwnProperty(key)来实现,如果不是,key 都不同就直接 return,如果 v2 确实也有,那就再判断,这里再次判断需要注意,value 也有可能还是个对象,那就递归
function equal(v1, v2) {
if ((typeof v1 === 'object' && v1 !== null) && (typeof v2 === 'object' && v2 !== null)) { // 都是引用类型

    for (let key in v1) {
        if (v2.hasOwnProperty(key)) { // 只要v1遍历的东西,V2显示具有就再去看value
            // 有可能value也是引用类型,那就递归下
            if (!equal(v1[key], v2[key])) {
                return false
            }
        } else {
            return false
        }
    }
} else { // 都不是引用类型、一方是引用类型 同样这也是递归的出口
    return v1 === v2
}

}

如果两个对象长得完全一样,那就意味着 for 循环,所有的递归走完了,也不会走到里面的 else,那就需要 for 循环结束后加一个返回 true
另外我们还可以进行优化,两个对象的 key 的数量若是不一致就是不一致
如何拿到对象的 key 的数量:Object.keys(obj),这个方法会以数组的形式返回对象的 key,所以直接.length 判断即可
最终代码实现如下
let arr = [1, 1, '2', 3, 1, 2,
{ name: '张三', id: { n: 1 } },
{ name: '张三', id: { n: 1 } },
{ name: '张三', id: { n: 2 } }
]

function uniqueArr (arr) {
let res = []
for (let item of arr) {
let isFind = false
for (let resItem of res) {
if (equal(item, resItem)) {
isFind = true
break
}
}
if (!isFind) res.push(item)
}
return res
}

function equal(v1, v2) {
if ((typeof v1 === 'object' && v1 !== null) && (typeof v2 === 'object' && v2 !== null)) { // 都是引用类型
if (Object.keys(v1).length !== Object.keys(v2).length) return false
for (let key in v1) {
if (v2.hasOwnProperty(key)) { // 只要v1遍历的东西,V2显示具有就再去看value
// 有可能value也是引用类型,那就递归下
if (!equal(v1[key], v2[key])) {
return false
}
} else {
return false
}
}
return true // 两个对象长得完全一样
} else { // 都不是引用类型、一方是引用类型 同样这也是递归的出口
return v1 === v2
}
}

console.log(uniqueArr(arr));

目录
相关文章
|
6月前
|
人工智能 JavaScript 前端开发
让OpenAi给我写个JS的set对象的笔记和快速去重方法
让OpenAi给我写个JS的set对象的笔记和快速去重方法
44 0
|
存储 监控 Java
Set集合去重(详细篇)
Set集合去重(详细篇)
197 0
|
存储 Java
引以为戒:避免在Set中使用未重写equals和hashCode的引用对象进行去重
在日常的Java开发中,我们经常会使用Set集合来实现去重操作,确保集合中不含有重复的元素。然而,如果使用未重写equals()和hashCode()方法的引用对象进行去重,可能会导致意外的行为,最近了在项目中就遇到了这个情况,让我们深入探讨这个问题,并引以为戒,确保正确实现去重操作。
64 0
引以为戒:避免在Set中使用未重写equals和hashCode的引用对象进行去重
|
存储 NoSQL 搜索推荐
【Redis从头学-7】Redis中的Set数据类型实战场景之用户画像去重、共同关注、专属粉丝
【Redis从头学-7】Redis中的Set数据类型实战场景之用户画像去重、共同关注、专属粉丝
293 0
数组双重去重的方式六set去重
数组双重去重的方式六set去重
52 0
|
C++ 容器
<C++>快速掌握set 容器|去重的底层原因|使用仿函数定义排序规则(下)
<C++>快速掌握set 容器|去重的底层原因|使用仿函数定义排序规则
200 0
|
C++ 容器
<C++>快速掌握set 容器|去重的底层原因|使用仿函数定义排序规则(上)
<C++>快速掌握set 容器|去重的底层原因|使用仿函数定义排序规则
226 0
|
JavaScript 前端开发
#yyds干货盘点# 【js学习笔记七】数组双重去重的方式六set去重
#yyds干货盘点# 【js学习笔记七】数组双重去重的方式六set去重
113 0
#yyds干货盘点# 【js学习笔记七】数组双重去重的方式六set去重
|
1月前
|
存储 JavaScript 前端开发
Set、Map、WeakSet 和 WeakMap 的区别
在 JavaScript 中,Set 和 Map 用于存储唯一值和键值对,支持多种操作方法,如添加、删除和检查元素。WeakSet 和 WeakMap 则存储弱引用的对象,有助于防止内存泄漏,适合特定场景使用。