当前位置: 首页 > news >正文

JavaScript数组键值去重方法

使用 filter 和 Map 根据键值去重

我来详细解释方法2,这是一种高效且简洁的数组去重方法,特别适合根据对象中的某个键值进行去重操作。

完整代码

function uniqueByKey(arr, key) {return [...new Map(arr.map(item => [item[key], item])).values()];
}

分步解析

让我们分解这个方法的每个步骤:

  1. arr.map(item => [item[key], item])

    • 遍历原始数组,为每个元素创建一个新数组

    • 新数组的第一个元素是对象的键值(item[key]

    • 第二个元素是对象本身(item

    • 例如,对于 {id: 1, name: 'John'},当 key 是 'id' 时,会变成 [1, {id: 1, name: 'John'}]

  2. new Map()

    • 将上一步生成的数组对传递给 Map 构造函数

    • Map 对象会自动处理键值对,当有相同的键时,后面的值会覆盖前面的值

    • 这是去重的关键步骤,因为 Map 的键必须是唯一的

  3. .values()

    • 获取 Map 中所有的值(即原始对象)

    • 这会返回一个 MapIterator 对象

  4. [... ]

    • 使用扩展运算符将 MapIterator 转换为普通数组

为什么这个方法有效?

  • Map 对象的特点是键必须是唯一的

  • 当我们把对象的键值作为 Map 的键,对象本身作为值时:

    • 如果遇到相同的键值,后面的对象会覆盖前面的对象

    • 最终 Map 中只保留每个键值的最后一个对象

  • 通过 values() 方法,我们只获取对象部分,忽略键

示例演示

假设我们有如下数组:

const data = [{id: 1, name: 'John'},{id: 2, name: 'Jane'},{id: 1, name: 'Johnny'},  // 重复的 id:1{id: 3, name: 'Alice'}
];

执行步骤:

  1. data.map(item => [item['id'], item]) 生成:

    [[1, {id: 1, name: 'John'}],[2, {id: 2, name: 'Jane'}],[1, {id: 1, name: 'Johnny'}],[3, {id: 3, name: 'Alice'}]
    ]
  2. new Map() 处理后:

    Map {1 => {id: 1, name: 'Johnny'},  // 后面的覆盖了前面的2 => {id: 2, name: 'Jane'},3 => {id: 3, name: 'Alice'}
    }
  3. .values() 获取:

    MapIterator {{id: 1, name: 'Johnny'},{id: 2, name: 'Jane'},{id: 3, name: 'Alice'}
    }
  4. [... ] 转换为数组:

    [{id: 1, name: 'Johnny'},{id: 2, name: 'Jane'},{id: 3, name: 'Alice'}
    ]

注意事项

  1. 保留最后一个重复项:这个方法会保留最后一个遇到的重复键值对象,而不是第一个

  2. 性能优势:对于大型数组,这种方法通常比其他方法(如使用 filter + find)性能更好,因为 Map 的查找操作是 O(1) 复杂度

  3. 键值类型:键值可以是任何类型,但会被 Map 转换为字符串形式进行比较

如果需要保留第一个遇到的重复项而不是最后一个,可以先将数组反转,处理后再反转回来:

function uniqueByKeyKeepFirst(arr, key) {return [...new Map([...arr].reverse().map(item => [item[key], item])).values()].reverse();
}
http://www.lryc.cn/news/583362.html

相关文章:

  • 【C++】容器适配器 + stack/queue/deque详解
  • EFK9.0.3 windows搭建
  • Ubuntu连接不上网络问题(Network is unreachable)
  • ubuntu环境下调试 RT-Thread
  • windows部署多实例filebeat监控相同路径下文件
  • 【Kafka】登录日志处理的三次阶梯式优化实践:从同步写入到Kafka多分区批处理
  • SAP-ABAP:SAP中DELECT语句用法详解实例总结
  • Go语言Gin框架实战:开发技巧
  • 2024 睿抗编程技能赛——省赛真题解析(含C++源码)
  • 【Python】遇到 “non-integer arg 1 for randrange() ” 问题的解决方法
  • 技术开发栈中 URL地址末尾加不加 “/“ 有什么区别?
  • 闲庭信步使用图像验证平台加速FPGA的开发:第六课——测试图案的FPGA实现
  • 解决IDEA缺少Add Framework Support选项的可行性方案
  • java中list.remove(item); // 直接移除会导致ConcurrentModificationException
  • 图像自动化处理初探:从拖拽上传到参数设置
  • 基于Java+Maven+Testng+Selenium+Log4j+Allure+Jenkins搭建一个WebUI自动化框架(5)失败用例截图与重试
  • 制作MikTex本地包可用于离线安装包
  • Synology Cloud Sync构建的企业级跨域数据中台
  • 前端性能优化:从之理论到实践的破局道
  • 【PTA数据结构 | C语言版】一元多项式求导
  • 使用 Docker 搭建 Rust Web 应用开发环境——AI教你学Docker
  • 图像处理中的凸包检测:原理与实现
  • 前端开发自动化设计详解
  • 两种方式清除已经保存的git账号密码
  • AI在垂直领域的深度应用:医疗、金融与自动驾驶的革新之路
  • 分治算法---快排
  • 深度帖:浏览器的事件循环与JS异步
  • Foundry智能合约测试设计流程
  • 【25软考网工】第十章 (3)网络冗余设计、广域网接入技术
  • 【一起来学AI大模型】PyTorch DataLoader 实战指南