JavaScript:从对象数组中提取具有唯一键值对的元素

JavaScript:从对象数组中提取具有唯一键值对的元素

本教程详细介绍了如何在javascript中处理一个对象数组,从每个对象中移除那些在数组中先前对象中已经出现过的重复键值对。通过构建一个高效的“已见”映射表,我们将逐步指导您实现一个函数,该函数能够生成一个仅包含在各自对象中首次出现的唯一键值对的新对象数组,从而确保数据去重并保持原始结构。

理解问题与目标

在处理复杂的数据结构时,我们经常会遇到需要去重的情况。本教程关注的是一个特定的去重场景:给定一个包含多个对象的数组,我们希望创建一个新的数组,其中每个对象只保留那些在整个处理过程中首次出现的键值对。这意味着,如果一个 key: value 对已经在数组中的某个先前对象中出现过,那么它在当前对象中就应该被移除。

让我们通过一个示例来具体说明:

原始输入数组:

const arr1 = [  {    "Param1": "20",    "Param2": "8",    "Param3": "11",    "Param4": "4",    "Param5": "18",    "Param6": "20",    "Param7": "8"  },  {    "Param6": "21",    "Param7": "8",    "Param8": "11",    "Param9": "4",    "Param10": "18"  },  {    "Param1": "20",    "Param2": "8",    "Param3": "10"  }];

期望输出数组:

立即学习“Java免费学习笔记(深入)”;

[  {    "Param1": "20",    "Param2": "8",    "Param3": "11",    "Param4": "4",    "Param5": "18",    "Param6": "20",    "Param7": "8"  },  {    "Param6": "21", // Param6: "20" 已在第一个对象中出现,但 Param6: "21" 是新的    "Param8": "11",    "Param9": "4",    "Param10": "18"  },  {    "Param3": "10" // Param1: "20" 和 Param2: "8" 已在第一个对象中出现  }]

可以看到,在第二个对象中,”Param7″: “8” 被移除了,因为它在第一个对象中已经出现过。同样,在第三个对象中,”Param1″: “20” 和 “Param2”: “8” 被移除,而 “Param3”: “10” 被保留,因为它与第一个对象中的 “Param3”: “11” 键相同但值不同,且 “Param3”: “10” 之前未出现过。

核心算法思路

要实现上述去重逻辑,我们需要一个机制来“记住”所有已经处理过的键值对。最有效的方法是使用一个“已见”映射表(seen map)。这个映射表将存储每个键以及该键所对应的值是否已被发现过的信息。

算法步骤如下:

初始化 seen 映射表: 创建一个空的 seen 对象(或 Map),其结构为 Record>,即 seen[key][value] = true 表示该键值对已被发现。初始化 result 数组: 创建一个空的数组来存放处理后的新对象。遍历输入数组: 逐个处理 arr1 中的每个对象。处理当前对象: 对于每个对象:创建一个新的空对象 currentUniqueObject。遍历当前对象中的所有键值对。对于每个键 key 和值 value:首先,检查 seen[key] 是否已存在。如果不存在,则初始化 seen[key] 为一个空对象 {}。接着,检查 seen[key][value] 是否为 true。如果为 true,表示这个 key: value 对之前已经出现过,因此我们忽略它。如果为 false 或 undefined,表示这个 key: value 对是首次出现。将其添加到 currentUniqueObject 中。将 seen[key][value] 设置为 true,标记为已见。添加结果: 将 currentUniqueObject 添加到 result 数组中。返回 result: 遍历完成后,返回 result 数组。

JavaScript 实现

我们可以利用 Array.prototype.reduce 方法来优雅地实现这个算法,它允许我们迭代数组并累积一个单一的结果(在这里是 seen 映射表和 result 数组的组合)。

/** * 从对象数组中移除在先前对象中已出现过的重复键值对。 * * @param arr 输入的对象数组,每个对象包含字符串键和字符串值。 * @returns 包含唯一键值对的新对象数组。 */const removeDuplicates = (arr: Record[]): Record[] => {    // 使用 reduce 方法来累积 'seen' 映射和 'result' 数组    return arr.reduce<{        seen: Record<string, Record>; // 存储已见键值对的映射        result: Record[];              // 存储处理后的结果数组    }>(        (accumulator, currentItem) => {            // 对于当前对象,筛选出唯一的键值对            const uniqueItem = Object.fromEntries(                Object.entries(currentItem).filter(([key, value]) => {                    // 确保 seen[key] 存在,如果不存在则初始化为 {}                    accumulator.seen[key] = accumulator.seen[key] ?? {};                    // 检查当前键值对是否已在 'seen' 映射中                    if (accumulator.seen[key][value]) {                        // 如果已见,则过滤掉(返回 false)                        return false;                    }                    // 如果未见,则标记为已见(设置为 true)                    accumulator.seen[key][value] = true;                    // 并保留该键值对(返回 true)                    return true;                }),            );            // 将处理后的唯一对象添加到结果数组中            accumulator.result.push(uniqueItem);            return accumulator;        },        // reduce 的初始值:一个包含空 'seen' 映射和空 'result' 数组的对象        { seen: {}, result: [] },    ).result; // 最后返回累加器中的 'result' 数组};

示例用法

现在,让我们将 removeDuplicates 函数应用于我们之前的示例数据:

const arr1 = [  {    "Param1": "20",    "Param2": "8",    "Param3": "11",    "Param4": "4",    "Param5": "18",    "Param6": "20",    "Param7": "8"  },  {    "Param6": "21",    "Param7": "8",    "Param8": "11",    "Param9": "4",    "Param10": "18"  },  {    "Param1": "20",    "Param2": "8",    "Param3": "10"  }];const uniqueArray = removeDuplicates(arr1);console.log(JSON.stringify(uniqueArray, null, 2));

输出结果:

[  {    "Param1": "20",    "Param2": "8",    "Param3": "11",    "Param4": "4",    "Param5": "18",    "Param6": "20",    "Param7": "8"  },  {    "Param6": "21",    "Param8": "11",    "Param9": "4",    "Param10": "18"  },  {    "Param3": "10"  }]

这个输出与我们预期的结果完全一致,成功地移除了所有重复的键值对。

注意事项与总结

数据类型限制: 本实现假设对象的值是字符串。如果值可以是其他类型(如数字、布尔值、对象等),seen 映射的键(value 部分)可能需要进行调整,例如使用 JSON.stringify 来确保唯一性,但这会带来性能开销。对于原始类型(字符串、数字等),当前方法是高效的。时间复杂度: 算法的时间复杂度大致为 O(N * K),其中 N 是输入数组中对象的数量,K 是每个对象中键值对的平均数量。这是因为我们需要遍历每个对象,并对每个对象的每个键值对进行查找和插入操作。空间复杂度: 空间复杂度主要取决于 seen 映射表的大小,它将存储所有不重复的键值对。在最坏情况下(所有键值对都不同),空间复杂度为 O(N * K)。不可变性: removeDuplicates 函数返回一个全新的数组和全新的对象,不会修改原始输入 arr1,这符合函数式编程的良好实践。

通过本教程,您已经学会了如何使用 Array.prototype.reduce 和一个自定义的“已见”映射表来高效地从对象数组中提取并保留那些在处理过程中首次出现的键值对。这种模式在处理需要基于历史状态进行数据过滤的场景中非常有用。

以上就是JavaScript:从对象数组中提取具有唯一键值对的元素的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1540613.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
JavaScript剪刀石头布函数深度解析:正则表达式与三元运算符的巧妙应用
上一篇 2025年12月21日 12:37:01
JavaScript中利用setInterval实现触发式弹窗的自动化开启与关闭
下一篇 2025年12月21日 12:37:16

相关推荐

  • 如何限制Linux用户可执行命令 sudo权限精细控制方案

    如何限制Linux用户可执行命令 sudo权限精细控制方案如何限制Linux用户可执行命令 sudo权限精细控制方案如何限制Linux用户可执行命令 sudo权限精细控制方案如何限制Linux用户可执行命令 sudo权限精细控制方案

    要安全配置linux的sudo权限,需遵循按需授权、最小权限和可追踪审计三大原则。1. 使用/etc/sudoers文件精细配置权限,推荐通过visudo编辑并验证语法,明确指定用户可执行的具体命令路径,可使用别名和nopasswd提升管理效率但需谨慎;2. 按用户组集中管理权限,创建特定权限组如w…

    2026年8月29日 用户投稿
    000
  • MySQL安全配置误区及防范_MySQL安全加固常见问题分析

    MySQL安全配置误区及防范_MySQL安全加固常见问题分析MySQL安全配置误区及防范_MySQL安全加固常见问题分析MySQL安全配置误区及防范_MySQL安全加固常见问题分析MySQL安全配置误区及防范_MySQL安全加固常见问题分析

    mysql安全配置误区在于依赖默认设置、忽视最小权限原则和网络暴露面管理不足。1.清理默认及不必要的账户,如匿名用户和test数据库;2.实施最小权限原则,为每个应用创建专属用户并仅授予必要权限;3.强化密码策略,使用validate_password插件强制复杂密码;4.收紧网络访问控制,限制bi…

    2026年8月29日 用户投稿
    000
  • 如何配置Linux用户资源限制 /etc/security/limits.conf详解

    如何配置Linux用户资源限制 /etc/security/limits.conf详解如何配置Linux用户资源限制 /etc/security/limits.conf详解如何配置Linux用户资源限制 /etc/security/limits.conf详解如何配置Linux用户资源限制 /etc/security/limits.conf详解

    linux用户资源限制通过编辑/etc/security/limits.conf文件配置,其核心语法为domain type item value。1. domain指定作用对象,如用户名、@组名或*(所有用户);2. type分为soft(可临时突破)和hard(不可突破);3. item为资源类…

    2026年8月29日 用户投稿
    100
  • 将 char[] 转换为 List:Arrays.asList() 的正确用法

    本文旨在深入解析 `Arrays.asList()` 方法在处理 `char[]` 数组时的行为。不同于 `Integer[]` 或 `String[]`,直接使用 `Arrays.asList()` 处理 `char[]` 会产生意外的结果,返回 `List` 而非预期的 `List`。本文将详细…

    2026年8月29日
    000
  • laravel8 字典管理是什么意思

    Laravel 8中字典管理涉及设计考量,包含:数据结构(分类、层级)、查询效率(索引)、缓存(Redis)和管理界面(Laravel Nova/Backpack)。该系统应考虑缓存过期时间调整、缓存失效策略以及错误处理和日志记录。 Laravel 8 字典管理?这可不是简单地往数据库里塞几行键值对…

    2026年8月29日
    000
  • 碧蓝航线新舰船优可可妮获取方法-碧蓝航线新舰船优可可妮该怎么获取

    碧蓝航线游戏中,在此次夏季活动之前,铁血阵营的活动中官方也为玩家们准备了不少新舰船和新皮肤。由于铁血以潜艇众多而出名,这次官方又推出了新的潜艇角色,下面就让我们一起来了解碧蓝航线新舰船优可可妮的获取方式。 碧蓝航线新舰船优可可妮获取方式如下:本次即将加入的是SSR稀有度的潜艇“优可可妮”!国服采用了…

    2026年8月29日
    100
  • # Laravel 中高效加载关联模型 ID 数组的实践指南

    本文旨在介绍如何在 Laravel 中高效地加载关联模型的 ID 数组,避免多次使用 `transform` 函数,并通过 `pluck` 方法、循环处理以及使用查询构建器等多种方式,优化数据查询性能,最终提供简洁且高效的代码示例。在 Laravel 开发中,经常会遇到需要加载关联模型,并且只需要关…

    2026年8月29日
    000
  • 电脑显卡驱动冲突导致游戏崩溃故障排查及解决方案

    电脑显卡驱动冲突导致游戏崩溃故障排查及解决方案电脑显卡驱动冲突导致游戏崩溃故障排查及解决方案电脑显卡驱动冲突导致游戏崩溃故障排查及解决方案电脑显卡驱动冲突导致游戏崩溃故障排查及解决方案

    显卡驱动冲突导致游戏崩溃的解决方法包括使用ddu彻底卸载旧驱动、安装匹配的新驱动并进入安全模式操作。首先,下载ddu工具和官方稳定版显卡驱动,并断开网络连接;其次,进入安全模式运行ddu选择对应显卡品牌进行清理并重启;接着,不联网状态下安装新驱动选择“自定义”或“高级安装”并勾选“执行清洁安装”,优…

    2026年8月29日 用户投稿
    000
  • VSCode怎么编写地图定位_VSCode集成地图API开发位置服务应用教程

    答案是集成地图API实现定位需选择服务商、引入SDK、初始化地图并调用定位功能。具体为:在VSCode中创建Web项目,引入百度等地图API的SDK,通过HTML页面加载地图容器,使用JavaScript初始化地图实例,并结合浏览器Geolocation API或地图SDK自带控件获取位置,最后添加…

    2026年8月29日
    000
  • 测试app开发成果?关键步骤!

    在app开发过程中,将创意转化为可运行的代码只是成功的一半。测试app才是确保最终产品符合预期、用户满意且市场表现良好的关键环节。忽略或轻视测试,往往导致糟糕的用户体验、负面评价,甚至业务损失。那么,如何系统有效地测试app开发成果?以下关键步骤必不可少: 制定详尽的测试计划与策略 明确目标: 测试…

    2026年8月29日
    400
  • workerman是怎么区分用户的

    WorkerMan区分用户的方式取决于连接ID,将连接ID与用户数据关联。具体方法包括:字典映射(低并发场景)、Redis哈希结构(高并发场景)、数据库(复杂数据管理)。优化要点:选择合适的数据存储、使用连接池、采用异步操作、处理错误、保证代码可读。 WorkerMan用户区分:深度剖析与最佳实践 …

    2026年8月29日
    100
  • 《优米雅的炼金工房》联动DLC上线 全新预告片与抽奖活动!

    《优米雅的炼金工房》联动DLC上线 全新预告片与抽奖活动!《优米雅的炼金工房》联动DLC上线 全新预告片与抽奖活动!《优米雅的炼金工房》联动DLC上线 全新预告片与抽奖活动!《优米雅的炼金工房》联动DLC上线 全新预告片与抽奖活动!

    近日,游戏开发商光荣特库摩正式宣布,《优米雅的炼金工房》将与《美德传奇f高清复刻版》展开联动合作,本次联动活动已正式上线。联动期间将推出免费的服装dlc内容,并同步开启抽奖活动,截止时间为2025年7月6日(星期日)。与此同时,全新的宣传视频也已发布,一起来了解一下详情吧! 宣传视频: 《优米雅的炼…

    2026年8月29日 用户投稿
    100
  • Java中如何将集合元素连接成一个字符串

    使用String.join()可直接连接字符串集合,Java 8可用Stream API的collect(Collectors.joining())处理任意类型,StringBuilder适合高性能场景。 在Java中,将集合元素连接成一个字符串有多种方式,最常用的是使用 String.join()…

    2026年8月29日
    100
  • ThinkPHP 队列(Queue)与异步任务处理

    在thinkphp中,可以使用队列来处理异步任务。具体方法包括:1.定义任务类并实现fire方法;2.使用queue::push方法将任务推送到队列中;3.通过配置驱动(如redis或数据库)来管理和执行任务。这种方式可以有效提升应用性能和用户体验。 引言 在现代Web开发中,异步任务处理和队列管理…

    2026年8月29日
    100
  • Mac+IDEA+百度富文本UEditor

    Mac+IDEA+百度富文本UEditorMac+IDEA+百度富文本UEditorMac+IDEA+百度富文本UEditorMac+IDEA+百度富文本UEditor

    最近,我在项目中需要嵌入一个富文本编辑器,考虑到百度ueditor的强大功能,决定使用它。然而,从%ignore_a_1%+eclipse环境转到mac+idea后,遇到了几个问题。经过一番努力,终于解决了这些问题,现分享我的经验。 环境:Mac + IDEA + UEditor 基于 Maven+…

    2026年8月29日 用户投稿
    200
  • 如何解决PHP项目中的图片缓存问题?使用Intervention/imagecache库可以!

    可以通过一下地址学习composer:学习地址 在处理图片密集型的php项目时,图片缓存是一个关键的优化策略。然而,实现一个高效的缓存机制并非易事,尤其是当涉及到多种图片处理操作时。幸运的是,intervention/imagecache库为我们提供了一个便捷且强大的解决方案。 安装与配置 首先,使…

    用户投稿 2026年8月29日
    100
  • 入门爬虫,不讲道理,只摆问题

    入门爬虫,不讲道理,只摆问题入门爬虫,不讲道理,只摆问题入门爬虫,不讲道理,只摆问题入门爬虫,不讲道理,只摆问题

    其实我也算是入门爬虫,目前也还有很多东西没有吃透,比如很多人入门选择使用的正则式我就没记清楚,对于很多反扒也并不算特别深入。但这并不影响我学习爬虫的信心和兴趣。。。没办法,必须要学啊。很多数据我不能跪着求别人给,因为别人不会给。。。被逼着学习爬虫,希望我的学习能有好结果吧 import json i…

    2026年8月28日 用户投稿
    100
  • VSCode怎么更改鼠标颜色_VSCode自定义鼠标指针颜色与样式教程

    答案:可通过修改VSCode设置自定义光标颜色、样式、粗细及闪烁方式以提升编码体验。具体包括在settings.json中配置editor.cursorStyle、editor.cursorWidth、editor.cursorBlinking,以及通过workbench.colorCustomiz…

    2026年8月28日
    100
  • 避免 jQuery AJAX POST 请求重复提交的策略与实践

    本文探讨了在使用 jQuery AJAX 进行 POST 请求时,如何有效避免因事件监听器、快速点击或意外行为导致的重复提交问题。我们将介绍一种基于状态标志的解决方案,通过控制请求的执行时机,确保数据提交的准确性和一致性,并提供相应的代码示例和最佳实践建议,以优化用户体验和系统稳定性。 问题描述:A…

    2026年8月28日
    200
  • Laravel vs Node.js(Express/NestJS):后端技术选型对比

    laravel 和 node.js 各有优劣,具体选择取决于项目需求和团队技能。1. laravel 适用于需要快速开发和丰富功能的项目,提供优雅的语法和强大的生态系统。2. node.js 适合高并发和实时功能的项目,性能优越且使用 javascript 便于开发。 引言 在后端开发的世界里,选择…

    2026年8月28日
    600

发表回复

登录后才能评论
关注微信