JS中提取完全唯一对象数组的正确实现方法
解决“提取完全唯一对象”的问题
我来帮你搞定这个需求!你要找的是数组中所有属性值都完全不与其他对象的任何属性值重复的对象,规则是保留先出现的、丢弃后续重复的。先聊聊你当前代码的问题,再给你正确的实现方案。
你的代码为什么不对?
你现在的实现是循环每个属性,逐个对数组做过滤:
for (let i in arr[0]) { let map = new Map(); arr = arr.filter(obj => map.get(obj[i]) ? false : map.set(obj[i], true)); }
这种做法是逐属性单独去重,比如先过滤出a属性唯一的对象,再在这个结果里过滤b属性唯一的……这和你的需求完全不符:
- 它没有全局跟踪所有已出现的属性值,只会检查当前属性在之前保留的对象里是否重复
- 会错误地删掉本该保留的对象,或者保留不符合“完全唯一”要求的对象
比如你的示例里,第四个对象的所有属性值都是全新的,但如果用你的代码,在过滤a属性时,第三个对象的a是a3,已经被Map记录了,第四个对象的a也是a3,会被直接过滤掉——但实际上第四个对象是符合要求的,因为它的其他属性值都没有重复。
正确的实现方式
核心思路是:维护一个全局集合,记录所有已经出现过的属性值;遍历数组时,检查当前对象的所有属性值是否都未在这个集合中出现过,是则保留并把这些值加入集合,否则丢弃。
代码如下:
const arr = [ { "a": "a1", "b": "b1", "c": "c1", "d": "d1", "e": "e1" }, { "a": "a2", "b": "b2", "c": "c2", "d": "d2", "e": "e2" }, { "a": "a3", "b": "b3", "c": "c2", "d": "d3", "e": "e3" }, { "a": "a3", "b": "b3", "c": "c3", "d": "d3", "e": "e3" } ]; // 全局存储所有已出现过的属性值 const usedValues = new Set(); const fullyUniqueObjects = arr.filter(obj => { // 获取当前对象的所有属性值 const allValues = Object.values(obj); // 检查所有值是否都未被使用过 const isFullyUnique = allValues.every(val => !usedValues.has(val)); if (isFullyUnique) { // 如果符合要求,把所有值加入已使用集合 allValues.forEach(val => usedValues.add(val)); return true; } return false; }); console.log(fullyUniqueObjects);
代码说明
usedValues全局集合:用来记录所有已经出现过的属性值,不管这些值属于哪个对象、哪个属性。- 过滤逻辑:
- 对每个对象,先取出它的所有属性值
allValues - 用
every检查每个值是否都不在usedValues中:只要有一个值重复,这个对象就不符合要求 - 如果所有值都是全新的,就把这些值全部加入
usedValues,同时保留这个对象到结果数组
- 对每个对象,先取出它的所有属性值
- 适配你的规则:因为是按数组顺序遍历,先出现的对象会优先保留,后续有重复值的对象会被过滤掉,完全符合你的需求。
运行这段代码后,输出结果就是你期望的数组:
[ { "a": "a1", "b": "b1", "c": "c1", "d": "d1", "e": "e1" }, { "a": "a2", "b": "b2", "c": "c2", "d": "d2", "e": "e2" }, { "a": "a3", "b": "b3", "c": "c3", "d": "d3", "e": "e3" } ]
内容的提问来源于stack exchange,提问作者brc-dd
相关产品推荐
相关产品推荐

