使用es6--对象数组的多种去重方式

本文分享了前端开发中数组及JSON数组的多种高效去重方法,包括使用ES6的Set、filter、forEach和reduce等现代JavaScript特性,简化代码并提高性能。

在当今这个前端代码时代,前端需要对数据处理的逻辑需求越来越多,也越来越复杂了;所以我在项目种总结了一些对去重的几种方式提供给到大家参考!

之前我是对数组去重是这样的,当然现在也没有被淘汰,还是可以用的只是代码看着有点l

demo:

  let array = ['amy','jack','tom','jackson','mark','jack'];

1:一维数组去重

beFore:
之前都是使用 indexOf, includes,

 var newArr = []
           for (var i = 0; i < array .length; i++) {
               if (newArr.indexOf(array [i])===-1) {
                    newArr.push(array [i])
              }
console.log(newArr)

Now: 使用es6:

var newArrStr = new Set(arr); //通过set集合去重;
//得到是字符串
 var newArr =Array.from(new Set(newArrStr));//数组

如何有多个数组只需将合并在去重即可

 var mergeArr= arr1.concat(arr2);

2 .JSON数组去重;

demo

  var obj1 = [{"id": 0, "name": "王嘉尔"},{"id": 1,"name": "段宜恩"},{"id": 0, "name": "林在范2"},];

 var obj2 = [{"id": 2, "name": "林在范"},{"id": 3,"name": "朴珍荣"},{ "id": 4,"name":"崔荣宰"},{ "id": 5,"name":"崔荣宰"},{ "id": 6,"name":"金有谦"}];

合并:

 var mergeObj= obj1 .concat(obj2 );

beFore:
在之前没有使用es6是这样的:

var new_arr=[];
var json_arr=[];
for(var i=0; i<obj2.length; i++){
    console.log(new_arr.indexOf(obj2[i][attribute]));
    if(new_arr.indexOf(obj2[i]['id']) ==-1){ 
        new_arr.push(obj2[i]['id']);  
        json_arr.push(obj2[i]);
    } else{
    }
}

console.log(json_arr);

你看看代码,十几行了;多L;咱们来看看 es6的强大;

Now: 使用es6:

2.1: filter&& forEach

//这种应用于添加数据业务需求


let newEs6Json =[];
obj2.forEach(item => {
    newEs6Json= obj1.filter(a  =>  a.spu != item.spu) 
 })
 console.log(newEs6Json );
 // [{"id": 0, "name": "王嘉尔"},{"id": 1,"name": "段宜恩"}]

2.2 reduce

 // let  obj3= obj1 .concat(obj2 );
 let new_obj ={};
 let peon =obj3.reduce((cur,next) => {
     obj[next.spu] ? "" : obj[next.spu] = true && cur.push(next);
      return cur;
 },[])

 console.log(peon);
 //[{"id": 0, "name": "王嘉尔"},{"id": 1,"name": "段宜恩"},{"id": 2, "name": "林在范"},{"id": 3,"name": "朴珍荣"},{ "id": 4,"name":"崔荣宰"},{ "id": 5,"name":"崔荣宰"},{ "id": 6,"name":"金有谦"}];

去重还是有很多种其他的方式的;我只能总结这么几个供大家参考了哈;

<think>好的,用户现在想了解如何对对象数组进行处理。之前我已经回答过普通数组的几种方法,现在需要针对对象数组的情况进行调整。首先,我需要回顾用户提供的引用内容,特别是引用1、2、3、4,这些涉及到对象数组的具体方法。用户可能已经看过这些方法,但需要更系统、清晰的解释和实现示例。 首先,我需要明确对象数组和普通数组的区别。普通数组可以直接比较值,但对象是引用类型,即使内容相同,不同的对象实例也不会被识别为重复。因此,对象数组需要基于特定属性或自定义规则来判断重复。比如,用户提到的引用中提到使用id属性作为唯一标识符。 接下来,我应该整理用户提供的引用中的方法,并参考之前的回答结构,分点说明不同的方法。引用1提到了使用reduce和Map,引用2和3提到了双层循环和reduce配合some或find方法,引用4使用了哈希表和reduce结合,引用5是普通数组,但可以忽略,因为用户现在需要对象数组的处理。 需要确保每种方法的实现示例正确,并指出其优缺点,比如时间复杂度、是否保持原顺序、是否修改原数组等。同时,用户之前的问题中的回答提到了哈希表法、Set、排序预处理等方法,但这些都是针对普通数组的,对象数组需要调整这些方法,比如使用对象属性作为哈希表的键。 另外,用户可能关心如何处理特殊数据类型,比如嵌套对象,或者多个属性组合作为唯一标识的情况。引用4中的方法允许指定一个键,但可能需要扩展到多个键的情况。需要说明如何实现这一点,比如将多个属性拼接成字符串作为哈希的键。 还需要注意代码示例的正确性,比如在JavaScript中使用对象作为哈希表时,属性名会被转换为字符串,可能导致意外行为,比如数字1和字符串"1"被视为相同键。此外,使用ES6的Map数据结构可以避免这个问题,因为键可以是任意类型。 最后,生成相关问题需要考虑用户可能的后续疑问,比如如何处理复杂对象的深度比较,或者性能优化方法,与之前的问题相呼应。</think>以下是对象数组的详细方法与实现,结合不同场景需求提供多种解决方案: --- ### 一、基于唯一标识符的方法 #### 1. **双层循环法**(时间复杂度$O(n^2)$) ```javascript function uniqueObjArray(arr, key) { for (let i = 0; i < arr.length; i++) { for (let j = i + 1; j < arr.length; j++) { if (arr[i][key] === arr[j][key]) { arr.splice(j, 1); // 删除重复项 j--; // 修正索引 } } } return arr; } ``` **特点**:直接修改原数组,适用于允许改变原数组的场景[^3]。 --- #### 2. **reduce + find 组合法**(时间复杂度$O(n^2)$) ```javascript function uniqueByReduce(arr, key) { return arr.reduce((acc, current) => { const isExist = acc.some(item => item[key] === current[key]); return isExist ? acc : [...acc, current]; }, []); } ``` **特点**:保持原数组顺序,生成新数组,适合需要保留首次出现项的场合[^2]。 --- #### 3. **哈希表优化法**(时间复杂度$O(n)$) ```javascript function uniqueByHash(arr, key) { const hash = {}; return arr.filter(item => hash[item[key]] ? false : (hash[item[key]] = true) ); } ``` **特点**:最高效的方案,但仅支持单一标识符判断,且会将键隐式转为字符串(如`1`和`"1"`会被视为相同)[^4]。 --- #### 4. **Map数据结构法**(ES6+,时间复杂度$O(n)$) ```javascript function uniqueByMap(arr, key) { const map = new Map(); return arr.filter(item => !map.has(item[key]) && map.set(item[key], true) ); } ``` **优势**:避免类型隐式转换问题,支持所有键类型(如对象、NaN等)[^1]。 --- ### 二、基于多属性组合的方法 当需要多个属性共同标识唯一性时: ```javascript function uniqueByMultiKeys(arr, keys) { const hash = {}; return arr.filter(item => { const keyStr = keys.map(k => item[k]).join('|'); // 生成复合键 return hash[keyStr] ? false : (hash[keyStr] = true); }); } // 使用示例:uniqueByMultiKeys(users, ['id', 'name']) ``` **适用场景**:需要多个属性联合判断唯一性(如用户ID+姓名)。 --- ### 三、深度比较(慎用) 针对嵌套对象或需要完全相同的结构: ```javascript function deepUnique(arr) { const seen = new Map(); return arr.filter(obj => { const key = JSON.stringify(obj); return seen.has(key) ? false : seen.set(key, true); }); } ``` **注意**:性能较低($O(n^2)$),且无法处理循环引用对象--- ### 四、性能对比与选择建议 | 方法 | 时间复杂度 | 是否保持顺序 | 适用场景 | |-----------------|------------|--------------|----------------------------| | 双层循环法 | $O(n^2)$ | 是 | 小数据量,简单 | | reduce法 | $O(n^2)$ | 是 | 需保留首次出现项 | | 哈希表法 | $O(n)$ | 是 | 大数据量,单一标识符 | | Map结构法 | $O(n)$ | 是 | 需严格类型判断 | | 多属性组合法 | $O(n)$ | 是 | 复合标识符 | --- ### 注意事项 1. **标识符选择**:确保选取的键能真正标识唯一性(如`id`而非可能重复的`name`) 2. **引用类型处理**:若标识符为对象属性(如`user.profile.id`),需确保属性存在 3. **性能陷阱**:避免在超大数据量(如10万+)中使用$O(n^2)$算法 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值