利用lodash对(对象)数组去重

使用场景:
根据数(对象)组中的id或者其他属性去重,或者对象中的所有属性值相同的去重。
传统方法:
通过数组的some进行逐项判断;
用了lodash之后发现还是很香的。

  import { isEqual, uniqWith, uniqBy } from 'lodash'
        let arr = [
      {id: 1, name: '冬雨', year: 18},
      {id: 2, name: '夏洛', year: 19},
      {id: 1, name: '秋雅', year: 20},
      {id: 3, name: '冬梅', year: 21},
      {id: 3, name: '冬雨', year: 18},
    ]
console.log('原数组:', arr);
console.log('根据id去掉相同的元素:', uniqBy(arr, 'id'));
console.log('检查数组每一项进行去重:', uniqWith(arr, isEqual));

在这里插入图片描述
前端遇到数据处理:
首先看一下lodash中是否有现成的方法,要善于利用工具,提升效率。

<think>嗯,用户现在问的是对象数组的问题。首先,我需要回想一下之前他们遇到的Vue警告问题,可能他们正在开发前端应用,处理数据时遇到了复的对象数组,需要。这时候,我应该考虑他们可能的数据结构和需求。 对象数组和普通数组不同,因为对象是引用类型,直接用Set或indexOf等方法可能不管用。用户可能已经尝试过一些方法但没成功,比如用JSON.stringify,但这种方法可能有缺陷,比如属性顺序不同或者包含函数等不可序列化的属性。 接下来,我需要考虑常见的解决方案。首先,使用filter和findIndex的组合,逐个检查元素是否已存在于新数组中。这种方法简单,但时间复杂度较高,适合小数据量。然后,使用临时对象或Map来存储唯一标识,比如某个属性值,如id,这样可以提高效率,但需要确保该属性唯一且存在。第三种方法是利用JSON.stringify将对象转为字符串,用Set,但需要注意其局限性。 另外,用户可能需要处理更复杂的情况,比如根据多个属性判断唯一性。这时候可能需要生成复合键,比如将多个属性值拼接成字符串作为键。还要考虑对象的嵌套问题,深比较可能会更准确,但性能开销大,可能需要权衡。 用户可能没有明确说明对象的结构,所以需要给出通用的方法,同时提醒他们根据实际情况调整。比如,如果对象有唯一标识符,推荐方法二;如果没有,可能需要使用方法一或三,但要注意潜在的问题。此外,性能也是一个考虑因素,大数据量下方法二的效率更高。 最后,要确保提供的代码示例正确,比如在方法一中,正确使用findIndex来比较已存在的对象,避免误判。同时,提醒用户关于JSON方法的注意事项,比如属性顺序和特殊类型处理。可能还需要提到使用第三方库如lodash的isEqual函数进行深度比较,但会增加依赖。 总结下来,应该分步骤介绍不同方法,说明原理、优缺点和适用场景,帮助用户根据具体情况选择最合适的解决方案。同时,保持回答结构清晰,便于用户理解和应用。</think>以下是针对**对象数组**的完整解决方案,根据不同的业务场景提供多种实现方式: --- ### **1. 基础(基于单一属性)** **适用场景**:对象中有唯一标识字段(如 `id`) ```javascript const arr = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 1, name: 'Alice' } // 复项 ]; // 使用Map存储已出现的id const uniqueArr = arr.filter((item, index, self) => index === self.findIndex(t => t.id === item.id) ); // 结果: [{id:1,name:'Alice'}, {id:2,name:'Bob'}] ``` --- ### **2. 高性能(O(n)时间复杂度)** **适用场景**:处理大数据量(10万+条数据) ```javascript const uniqueByKey = (arr, key) => { const seen = new Map(); return arr.filter(item => { const identifier = item[key]; return seen.has(identifier) ? false : seen.set(identifier, true); }); }; // 使用示例 uniqueByKey(arr, 'id'); // 以id为唯一标识 ``` --- ### **3. 复合键** **适用场景**:需要多个字段组合判断唯一性 ```javascript const uniqueByKeys = (arr, keys) => { const seen = new Set(); return arr.filter(item => { const compositeKey = keys.map(k => item[k]).join('|'); return seen.has(compositeKey) ? false : seen.add(compositeKey); }); }; // 使用示例:根据id和name联合 uniqueByKeys(arr, ['id', 'name']); ``` --- ### **4. 深度对比(谨慎使用)** **适用场景**:需要完全相同的对象副本检测 ```javascript const deepUnique = (arr) => { const seen = new Set(); return arr.filter(item => { const str = JSON.stringify(item); return seen.has(str) ? false : seen.add(str); }); }; // 注意:此方法有局限性(无法处理属性顺序变化、函数属性等) ``` --- ### **5. 使用ES6特性优化版** ```javascript const uniqueBy = (arr, keyExtractor) => { return [...new Map(arr.map(item => [keyExtractor(item), item])).values()]; }; // 使用示例 uniqueBy(arr, item => item.id); // 提取唯一键 ``` --- ### **关键问题分析** | 方法 | 时间复杂度 | 优点 | 缺点 | |------|------------|------|------| | 基础方法 | O() | 无需预知数据结构 | 性能差 | | Map存储 | O(n) | 高效大数据处理 | 需明确唯一键 | | 复合键 | O(n) | 支持多字段 | 需预定义组合规则 | | JSON法 | O(n) | 简单暴力 | 无法处理特殊对象 | --- ### **常见陷阱** 1. **引用类型陷阱**: ```javascript // 这两个对象看似相同,实则不同 {a:1} !== {a:1} // true ``` 2. **undefined处理**: ```javascript // 当key值为undefined时的处理 uniqueByKey([{id: undefined}, {id: undefined}], 'id') // 结果为单元素数组 ``` 3. **NaN处理**: ```javascript // Map的key会认为NaN === NaN const arr = [{id: NaN}, {id: NaN}]; uniqueByKey(arr, 'id'); // 正确 ``` --- ### **最佳实践建议** 1. **优先使用显式标识字段**(如数据库主键) 2. 超过1000条数据时选择`Map`方案 3. 需要模糊匹配时考虑使用`Lodash的_.isEqual` ```javascript import _ from 'lodash'; arr.filter((item, index) => index === arr.findIndex(t => _.isEqual(t, item)) ); ``` --- ### **扩展:TypeScript实现** ```typescript function uniqueBy<T>(arr: T[], key: keyof T): T[] { return [...new Map(arr.map(item => [item[key], item])).values
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值