JavaScript中根据键值比较两个对象并计算总和的教程

JavaScript中根据键值比较两个对象并计算总和的教程

本教程旨在指导开发者如何在javascript中,依据一个嵌套对象(`values`)的键值,从另一个对象(`points`)中匹配并计算相应分数的总和。文章提供了多种实现策略,包括使用`reduce`进行迭代聚合,以及通过构建查找表进行高效数据匹配和求和,以满足复杂的数据处理需求。

在前端开发中,我们经常会遇到需要处理结构化数据并进行聚合计算的场景。一个典型的例子是,我们有两个JavaScript对象:一个包含用户选择或状态的嵌套对象,另一个则存储了这些选择对应的分数。我们的目标是根据第一个对象的键值,从第二个对象中查找对应的分数并计算总和。

考虑以下两个JavaScript对象作为示例数据:

const values = {    Q1: {        Q1A1: "Yes",    },    Q2: {        Q2A1: "Yes",    },    Q3: {        Q3A2: "No",    },};const points = {    Q1A1: 41,    Q1A2: 0,    Q2A1: 19,    Q2A2: 0,    Q3A1: 25,    Q3A2: 0, // 假设这里是0,如果题目要求Q3A2="No"不计分,则即使这里是5也应忽略};

我们的目标是根据values对象中嵌套的键(例如Q1A1、Q2A1)以及它们的值(例如”Yes”),从points对象中查找对应的分数并求和。例如,如果Q1A1是”Yes”,则计入points.Q1A1的分数;如果Q3A2是”No”,则不计分。最终结果应为41 + 19 = 60。

接下来,我们将探讨几种实现这一目标的JavaScript方法。

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

方法一:使用嵌套 reduce 进行直接聚合

这种方法通过两次 reduce 迭代,直接遍历 values 对象的结构,并在满足条件时累加分数。

const values = {    Q1: { Q1A1: "Yes" },    Q2: { Q2A1: "Yes" },    Q3: { Q3A2: "No" },};const points = {    Q1A1: 41,    Q1A2: 0,    Q2A1: 19,    Q2A2: 0,    Q3A1: 25,    Q3A2: 5, // 假设这里是5,但由于Q3A2="No",此值不应被计入};const total = Object.values(values) // 获取values对象中所有Q1, Q2, Q3等子对象  .reduce((acc, cur) => { // 外层reduce用于遍历Q1, Q2, Q3等    return acc + Object.entries(cur) // 获取当前子对象(如{Q1A1: "Yes"})的键值对      .reduce((accInner, [key, val]) => { // 内层reduce用于遍历子对象中的键值对        // 判断条件:值不为'No' 且 points对象中存在对应的key,且其值为有效分数(非0或undefined)        // 注意:如果points[key]可能是0,但0也应该计入,则只需判断 points[key] !== undefined        if (val !== 'No' && points[key] !== undefined && points[key] !== null) {          return accInner + points[key];        }        return accInner;      }, 0); // 内层reduce的初始累加值为0  }, 0); // 外层reduce的初始累加值为0console.log(total); // 输出: 60

解析:

Object.values(values):首先提取 values 对象中所有第一层的值,即 Q1, Q2, Q3 等子对象。外层 reduce:遍历这些子对象。acc 是总累加器,cur 是当前的子对象(例如 { Q1A1: “Yes” })。Object.entries(cur):对于每个子对象,提取其键值对数组(例如 [[‘Q1A1’, ‘Yes’]])。内层 reduce:遍历子对象的键值对。accInner 是当前子对象的分数累加器,[key, val] 是当前的键值对。条件判断:val !== ‘No’ 确保只有非”No”的答案才考虑计分。points[key] !== undefined && points[key] !== null 确保在 points 对象中存在对应的键,并且其值有效。如果points[key]可能为0且0也应计入,则只需 points[key] !== undefined。如果条件满足,将 points[key] 的值加到 accInner 中。

这种方法简洁,直接在迭代过程中完成计算,适用于数据结构相对固定的情况。

方法二:构建查找表后进行过滤和求和

当数据量较大或需要更清晰地分离数据处理步骤时,可以先从 values 对象中构建一个符合条件的键的查找表,然后再用这个查找表去过滤和累加 points 对象中的分数。

const values = {    Q1: { Q1A1: "Yes" },    Q2: { Q2A1: "Yes" },    Q3: { Q3A2: "No" },};const points = {    Q1A1: 41,    Q1A2: 0,    Q2A1: 19,    Q2A2: 0,    Q3A1: 25,    Q3A2: 5,};// 步骤1: 从values对象中构建一个符合条件的键的查找表const lookupKeys = Object.values(values).reduce((acc, cur) => {  // 假设每个子对象只有一个键值对  const [key, val] = Object.entries(cur)[0];  if (val === "Yes") { // 只有值为"Yes"的键才被添加到查找表中    acc[key] = true; // 使用布尔值作为查找表的值,表示该键存在且符合条件  }  return acc;}, {});console.log("Lookup Table:", lookupKeys); // 输出: { Q1A1: true, Q2A1: true }// 步骤2: 遍历points对象,根据查找表过滤并求和const total = Object.entries(points)  .filter(([key, score]) => lookupKeys[key] && score !== 0) // 过滤条件:键在查找表中存在 且 分数不为0  .reduce((accumulator, [key, score]) => accumulator + score, 0); // 对过滤后的分数进行累加console.log(total); // 输出: 60

解析:

构建 lookupKeys:Object.values(values).reduce(…):遍历 values 对象的子对象。Object.entries(cur)[0]:获取每个子对象内部的第一个(也是唯一一个)键值对。if (val === “Yes”) acc[key] = true;:如果值是 “Yes”,则将该键添加到 lookupKeys 对象中,值为 true,表示这是一个需要计分的有效键。过滤并求和:Object.entries(points):将 points 对象转换为键值对数组。.filter(([key, score]) => lookupKeys[key] && score !== 0):过滤这些键值对。只有当键存在于 lookupKeys 中(即 lookupKeys[key] 为 true)并且分数不为 0 时,才保留该项。.reduce((accumulator, [key, score]) => accumulator + score, 0):对过滤后的项进行累加,得到最终总和。

这种方法将数据准备和计算分成了两个清晰的阶段,提高了代码的可读性和模块化。

方法三:提取所有相关键到 Set 后进行过滤和求和

如果我们的条件仅仅是“values 对象中存在的键,无论其值是Yes还是No,只要在points中有对应分数就计入”,或者我们只关心特定条件的键(如”Yes”),并希望高效地检查键的存在性,可以使用 Set 结构来存储符合条件的键。

const values = {    Q1: { Q1A1: "Yes" },    Q2: { Q2A1: "Yes" },    Q3: { Q3A2: "No" },};const points = {    Q1A1: 41,    Q1A2: 0,    Q2A1: 19,    Q2A2: 0,    Q3A1: 25,    Q3A2: 5,};// 步骤1: 从values对象中提取所有符合条件的键到Setconst pointKeysToSum = Object.values(values).reduce((acc, cur) => {  const [key, val] = Object.entries(cur)[0]; // 获取子对象中的键值对  if (val === "Yes") { // 假设我们只关心值为"Yes"的键    acc.add(key); // 将符合条件的键添加到Set中  }  return acc;}, new Set()); // 初始值为一个空的Setconsole.log("Keys to Sum (Set):", pointKeysToSum); // 输出: Set(2) { 'Q1A1', 'Q2A1' }// 步骤2: 遍历points对象,根据Set过滤并求和const total = Object.entries(points)  .filter(([key, score]) => pointKeysToSum.has(key)) // 过滤条件:键存在于Set中  .reduce((accumulator, [key, score]) => accumulator + score, 0); // 对过滤后的分数进行累加console.log(total); // 输出: 60

解析:

构建 pointKeysToSum Set:Object.values(values).reduce(…):遍历 values 对象的子对象。if (val === “Yes”) acc.add(key);:根据条件(此处为 val === “Yes”)将键添加到 Set 中。Set 自动处理重复键,确保每个键只出现一次。过滤并求和:Object.entries(points):将 points 对象转换为键值对数组。.filter(([key, score]) => pointKeysToSum.has(key)):使用 Set.prototype.has() 方法高效地检查键是否存在于 pointKeysToSum 中。.reduce((accumulator, [key, score]) => accumulator + score, 0):对过滤后的项进行累加。

Set 的 has() 方法具有平均 O(1) 的时间复杂度,这使得它在处理大量键的查找时比数组的 includes() 方法(O(n))更高效。

注意事项与总结

条件逻辑: 教程中演示了根据 val === “Yes” 或 val !== “No” 进行判断。实际应用中,你需要根据具体业务需求调整条件。键值类型: 确保 values 中提取的键与 points 中的键类型一致(通常都是字符串)。分数有效性: 在累加分数时,考虑 points[key] 可能为 undefined、null 或 0 的情况。根据业务需求决定这些值是否应该计入总和。数据结构假设: 示例中 values 对象的每个子对象(如 Q1)内部只有一个键值对。如果存在多个,你需要调整 Object.entries(cur)[0] 的逻辑,可能需要再次迭代。性能考量:对于小型数据集,所有方法性能差异不大。对于大型数据集,Set 或构建查找表(方法二和方法三)通常比嵌套 reduce(方法一)更具优势,因为它们将查找操作的复杂度从 O(N*M) 降低到 O(N+M),其中 N 和 M 分别是两个对象的大小。Set.prototype.has() 的 O(1) 平均时间复杂度在查找效率上表现突出。可读性: 选择最能清晰表达意图的方法。对于复杂逻辑,分阶段构建查找表或 Set 可能比深度嵌套的 reduce 更易读。

通过本文介绍的几种方法,你可以根据实际需求和偏好,灵活选择在JavaScript中根据键值比较两个对象并计算总和的最佳策略。理解这些数组和对象方法的强大功能,将有助于你更高效地处理各种数据聚合任务。

以上就是JavaScript中根据键值比较两个对象并计算总和的教程的详细内容,更多请关注创想鸟其它相关文章!

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

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Javascript如何进行模块化开发?
上一篇 2025年12月21日 13:35:51
NextAuth应用中访问令牌的安全管理:会话存储与刷新机制
下一篇 2025年12月21日 13:36:03

相关推荐

  • 构建健壮的Java用户输入:Scanner整数解析与异常捕获

    构建健壮的Java用户输入:Scanner整数解析与异常捕获构建健壮的Java用户输入:Scanner整数解析与异常捕获构建健壮的Java用户输入:Scanner整数解析与异常捕获构建健壮的Java用户输入:Scanner整数解析与异常捕获

    本文深入探讨了Java Scanner在获取整数输入时,当用户输入非整数数据可能引发的InputMismatchException。我们将解释此异常的产生机制,并提供一种健壮的解决方案:通过结合try-catch语句有效捕获并处理该异常,从而避免程序崩溃,提升用户交互的稳定性与友好性。 1. Jav…

    2026年9月26日 • 用户投稿
    000
  • VS Code工作台定制:活动栏与面板可见性配置指南

    隐藏活动栏可通过命令面板执行“View: Toggle Activity Bar Visibility”或设置”workbench.activityBar.visible”: false;2. 面板可用Ctrl+J切换显示,通过”workbench.panel.d…

    2026年9月26日
    000
  • 《少林vs武当:传奇》上架Steam 暂不支持中文

    《少林vs武当:传奇》上架Steam 暂不支持中文《少林vs武当:传奇》上架Steam 暂不支持中文《少林vs武当:传奇》上架Steam 暂不支持中文《少林vs武当:传奇》上架Steam 暂不支持中文

    近日,格斗游戏新作《少林vs武当:传奇》(shaolin vs wutang legends)正式登陆steam平台,目前尚未公布具体发售时间,且暂未提供中文支持。 Steam商店页面:[点击前往](https://www.php.cn/link/b1a5a84a3388b3f37634445bd1…

    2026年9月26日 • 用户投稿
    000
  • 如何在Java中使用protected修饰符

    protected成员可在同类、同包及其他包的子类中访问,主要用于继承;子类不能通过父类实例访问其protected成员,只能继承访问。 在Java中,protected 是一种访问修饰符,用于控制类成员(字段、方法、构造器或内部类)的可见性。它比 private 更宽松,但比 public 更严格…

    2026年9月26日
    100
  • 如何在Java方法中正确传递和使用数组参数

    如何在Java方法中正确传递和使用数组参数如何在Java方法中正确传递和使用数组参数如何在Java方法中正确传递和使用数组参数如何在Java方法中正确传递和使用数组参数

    本文旨在帮助Java初学者理解如何在方法中正确传递和使用数组作为参数。通过一个实际的代码示例,详细讲解了如何创建、传递和访问数组,以及如何在方法内部对数组进行操作,最终返回期望的结果。掌握这些技巧对于编写高效且功能完善的Java程序至关重要。 在Java编程中,方法经常需要接收数组作为参数,以便对一…

    2026年9月26日 • 用户投稿
    500
  • Linux如何从源码编译安装软件_configure与make命令详解

    Linux如何从源码编译安装软件_configure与make命令详解Linux如何从源码编译安装软件_configure与make命令详解Linux如何从源码编译安装软件_configure与make命令详解Linux如何从源码编译安装软件_configure与make命令详解

    答案是掌握 ./configure 和 make 的作用与用法可完成 Linux 源码编译安装。1. configure 检查系统环境并生成 Makefile,确保编译条件满足,支持 –prefix、–enable、–with 等选项定制安装;2. make 读取…

    2026年9月26日 • 用户投稿
    000
  • Java 方法中数组参数的正确调用方式

    Java 方法中数组参数的正确调用方式Java 方法中数组参数的正确调用方式Java 方法中数组参数的正确调用方式Java 方法中数组参数的正确调用方式

    本文旨在阐述如何在 Java 方法中正确传递和使用数组参数。通过一个实际的例子,我们将详细讲解如何创建数组、将其作为参数传递给方法,以及如何在方法内部访问和操作数组元素。掌握这些技巧对于编写高效且易于维护的 Java 代码至关重要。 在 Java 编程中,方法经常需要接收数组作为参数,以便对一组数据…

    2026年9月26日 • 用户投稿
    000
  • 从Scanner读取单个字符时处理空格的问题

    从Scanner读取单个字符时处理空格的问题从Scanner读取单个字符时处理空格的问题从Scanner读取单个字符时处理空格的问题从Scanner读取单个字符时处理空格的问题

    本文旨在解决Java中使用Scanner读取用户输入时,由于Scanner默认以空格作为分隔符,导致读取单个字符时出现的问题。我们将深入探讨Scanner的工作原理,并提供使用Scanner.nextLine()方法读取整行输入来解决此问题的方案,确保程序能够正确处理包含空格的输入。 在使用Java…

    2026年9月26日 • 用户投稿
    100
  • ChatGPT如何生成结构化内容 表格、JSON等格式生成技巧分享

    ChatGPT如何生成结构化内容 表格、JSON等格式生成技巧分享ChatGPT如何生成结构化内容 表格、JSON等格式生成技巧分享ChatGPT如何生成结构化内容 表格、JSON等格式生成技巧分享ChatGPT如何生成结构化内容 表格、JSON等格式生成技巧分享

    本文将围绕如何引导模型生成表格和JSON等结构化数据进行详细叙述。我们将通过分步讲解的方式,介绍如何通过构建精确的提示词,让模型理解并输出您所需要的特定格式,从而帮助您掌握这一实用技巧,方便您在学习和工作中直接应用。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSe…

    2026年9月26日 • 用户投稿
    100
  • 从 0 开始学 V8 漏洞利用之 V8 通用利用链(二)

    作者:hcamael@知道创宇404实验室 相关阅读:从 0 开始学 V8 漏洞利用之环境搭建(一)经过一段时间的研究,先进行一波总结,不过因为刚开始研究没多久,也许有一些局限性,以后如果发现了,再进行修正。 概述 ‍我认为,在搞漏洞利用前都得明确目标。比如打CTF做二进制的题目,大部分情况下,目标…

    2026年9月26日
    100
  • x浏览器如何拦截弹窗广告_x浏览器弹窗广告拦截教程

    x浏览器如何拦截弹窗广告_x浏览器弹窗广告拦截教程x浏览器如何拦截弹窗广告_x浏览器弹窗广告拦截教程x浏览器如何拦截弹窗广告_x浏览器弹窗广告拦截教程x浏览器如何拦截弹窗广告_x浏览器弹窗广告拦截教程

    开启x浏览器广告拦截功能可有效屏蔽弹窗广告。首先在设置中启用“广告过滤”并选择强力模式;其次通过自定义规则添加已知广告域名进行精准拦截;接着在隐私与安全设置中开启“阻止弹出窗口”开关,阻断脚本触发的弹窗;最后可使用轻阅读模式简化网页结构,避免广告加载,提升浏览体验。 如果您在浏览网页时频繁遇到弹窗广…

    2026年9月26日 • 用户投稿
    300
  • MAC连接的移动硬盘速度很慢_Mac外置硬盘读写速度慢问题排查

    MAC连接的移动硬盘速度很慢_Mac外置硬盘读写速度慢问题排查MAC连接的移动硬盘速度很慢_Mac外置硬盘读写速度慢问题排查MAC连接的移动硬盘速度很慢_Mac外置硬盘读写速度慢问题排查MAC连接的移动硬盘速度很慢_Mac外置硬盘读写速度慢问题排查

    答案:Mac连接移动硬盘速度慢可能因存储不足、接口问题或硬盘故障等导致。应清理硬盘空间至10%-15%以上,更换为USB 3.0及以上数据线并直连主机端口,使用“磁盘工具”检查健康状况并修复错误,通过“活动监视器”终止高占用进程,并确保硬盘采用APFS或exFAT等合适文件系统以提升性能。 如果您在…

    2026年9月26日 • 用户投稿
    300
  • sublime怎么解决mac上无法使用命令行subl的问题_sublime Mac命令行Subl问题解决

    sublime怎么解决mac上无法使用命令行subl的问题_sublime Mac命令行Subl问题解决sublime怎么解决mac上无法使用命令行subl的问题_sublime Mac命令行Subl问题解决sublime怎么解决mac上无法使用命令行subl的问题_sublime Mac命令行Subl问题解决sublime怎么解决mac上无法使用命令行subl的问题_sublime Mac命令行Subl问题解决

    首先确认Sublime Text已安装在/Applications/Sublime Text.app,然后通过sudo ln -s /Applications/Sublime Text.app/Contents/SharedSupport/bin/subl /usr/local/bin/subl创建…

    2026年9月26日 • 用户投稿
    100
  • 什么是线程池?为什么使用线程池?ThreadPoolExecutor有哪些核心参数?

    什么是线程池?为什么使用线程池?ThreadPoolExecutor有哪些核心参数?什么是线程池?为什么使用线程池?ThreadPoolExecutor有哪些核心参数?什么是线程池?为什么使用线程池?ThreadPoolExecutor有哪些核心参数?什么是线程池?为什么使用线程池?ThreadPoolExecutor有哪些核心参数?

    线程池通过复用预先创建的线程,避免频繁创建销毁带来的开销,提升系统性能与稳定性。ThreadPoolExecutor是Java中实现线程池的核心类,其核心参数包括corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(非核心线程空闲存活时间)…

    2026年9月26日 • 用户投稿
    100
  • 使用构造器注入替代 @Autowired 注解

    使用构造器注入替代 @Autowired 注解使用构造器注入替代 @Autowired 注解使用构造器注入替代 @Autowired 注解使用构造器注入替代 @Autowired 注解

    本文旨在讲解如何使用构造器注入来替代 Spring 框架中的 @Autowired 注解,从而实现更简洁、更易于测试的代码。我们将通过一个实际案例,展示如何利用 Lombok 提供的 @AllArgsConstructor 注解简化构造器注入的过程,并解决可能遇到的问题,最终避免手动创建 Bean。…

    2026年9月26日 • 用户投稿
    100
  • 如何在Java中实现对象克隆

    答案是Java中实现对象克隆需实现Cloneable接口并重写clone()方法,分为浅克隆和深克隆:浅克隆复制基本类型字段值,引用类型仅复制地址;深克隆则递归复制所有对象,确保完全独立。可通过手动克隆引用字段或序列化实现深克隆,使用时需注意异常处理、访问权限及可变对象的隔离问题,尽管克隆机制存在但…

    2026年9月26日
    200
  • Debian上TigerVNC共享文件方法

    Debian上TigerVNC共享文件方法Debian上TigerVNC共享文件方法Debian上TigerVNC共享文件方法Debian上TigerVNC共享文件方法

    本文介绍如何在Debian系统上使用TigerVNC共享文件。 你需要先安装TigerVNC服务器,然后进行配置。 一、安装TigerVNC服务器 打开终端。更新软件包列表:sudo apt update安装TigerVNC服务器:sudo apt install tigervnc-standalo…

    2026年9月26日 • 用户投稿
    000
  • 如何通过豆包AI进行异常检测?离群值分析实战

    如何通过豆包AI进行异常检测?离群值分析实战如何通过豆包AI进行异常检测?离群值分析实战如何通过豆包AI进行异常检测?离群值分析实战如何通过豆包AI进行异常检测?离群值分析实战

    异常检测是识别数据集中不符合预期模式的数据点的过程,这些“异常”可能由错误、欺诈、设备故障等引起,在金融、网络安全、制造质量控制等领域具有重要意义。常见方法包括基于统计的z-score、iqr法;基于距离的knn;孤立森林;one-class svm;以及深度学习中的自编码器。其中孤立森林因高效性和…

    2026年9月26日 • 用户投稿
    100
  • 对象创建的主要流程是怎样的?(类加载检查、分配内存、初始化等)

    对象创建的主要流程是怎样的?(类加载检查、分配内存、初始化等)对象创建的主要流程是怎样的?(类加载检查、分配内存、初始化等)对象创建的主要流程是怎样的?(类加载检查、分配内存、初始化等)对象创建的主要流程是怎样的?(类加载检查、分配内存、初始化等)

    对象创建需经历类加载检查、内存分配和初始化三阶段。首先JVM检查类是否已加载,确保类结构合法并完成静态资源准备;随后在堆中为对象分配内存,采用指针碰撞或空闲列表方式,并通过TLAB或CAS解决并发问题;最后进行初始化,先将内存置零,设置对象头信息,再执行构造器完成实例化。类加载是前提,保障类型安全与…

    2026年9月26日 • 用户投稿
    100
  • windows更新失败错误0x80070002怎么办_错误代码0x80070002更新失败修复策略

    windows更新失败错误0x80070002怎么办_错误代码0x80070002更新失败修复策略windows更新失败错误0x80070002怎么办_错误代码0x80070002更新失败修复策略windows更新失败错误0x80070002怎么办_错误代码0x80070002更新失败修复策略windows更新失败错误0x80070002怎么办_错误代码0x80070002更新失败修复策略

    0x80070002错误通常因更新文件丢失或服务异常导致。1、重启Windows Update和BITS服务;2、清除C:WindowsSoftwareDistribution缓存;3、运行sfc /scannow和DISM修复系统文件;4、使用系统内置的Windows Update疑难解答工具自动…

    2026年9月26日 • 用户投稿
    100

发表回复

登录后才能评论
关注微信