0

0

如何在 JavaScript 中根据键值比较两个对象并计算总和

心靈之曲

心靈之曲

发布时间:2025-12-05 15:30:27

|

448人浏览过

|

来源于php中文网

原创

如何在 JavaScript 中根据键值比较两个对象并计算总和

本文旨在指导读者如何在 javascript 中有效地根据两个对象的键值进行比较并计算特定属性的总和。我们将探讨多种实现策略,包括利用 `reduce` 方法进行链式操作,以及通过构建查找表或键集合来简化逻辑,最终实现对匹配项分数的累加。

在 JavaScript 开发中,我们经常需要处理结构化数据,并根据特定条件对数据进行聚合。一个常见的场景是,我们有两个对象:一个包含用户的选择或答案,另一个则存储了所有可能选项对应的分数。我们的目标是根据用户的选择,从分数对象中找出对应的分数并计算总和。

场景描述与数据结构

假设我们有以下两个 JavaScript 对象:

  1. values 对象:代表用户的选择或答案。它是一个嵌套对象,外层键通常代表问题 ID(如 Q1),内层对象包含用户选择的答案 ID(如 Q1A1)及其对应的状态(如 "Yes" 或 "No")。
  2. points 对象:存储了所有可能的答案 ID 及其对应的分数。它是一个扁平对象,键是答案 ID,值是分数。

示例数据:

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,
};

根据上述数据,如果用户选择了 Q1A1 ("Yes") 和 Q2A1 ("Yes"),并且 Q3A2 ("No") 不计入分数,那么期望的总和是 points.Q1A1 (41) + points.Q2A1 (19) = 60。

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

接下来,我们将介绍几种实现此计算的方法。

方法一:使用嵌套的 reduce 方法

这种方法利用 Array.prototype.reduce() 的强大功能,通过两次迭代来聚合数据。外层 reduce 遍历 values 对象的问题,内层 reduce 遍历每个问题下的答案。

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, // 即使有分,如果 'No' 也不计
};

const total = Object.values(values) // 获取 values 对象的所有值 (即 Q1, Q2, Q3 对应的子对象)
  .reduce((acc, cur) => { // 外层 reduce 累加每个问题下的分数
    return acc + Object.entries(cur) // 获取当前问题子对象的所有键值对 (如 ['Q1A1', 'Yes'])
      .reduce((accInner, [key, val]) => { // 内层 reduce 处理单个答案
        // 检查答案值是否不为 'No' 且 points 对象中存在对应的键
        if (val !== 'No' && points[key]) {
          return accInner + points[key]; // 如果满足条件,累加对应的分数
        }
        return accInner; // 否则不累加
      }, 0); // 内层 reduce 的初始累加值为 0
  }, 0); // 外层 reduce 的初始累加值为 0

console.log(total); // 输出: 60

解释:

吐槽大师
吐槽大师

吐槽大师(Roast Master) - 终极 AI 吐槽生成器,适用于 Instagram,Facebook,Twitter,Threads 和 Linkedin

下载
  1. Object.values(values):将 values 对象转换为一个数组,其中包含 Q1, Q2, Q3 对应的子对象。
  2. 外层 reduce:遍历这些子对象,acc 是总分数累加器,cur 是当前的问题子对象(例如 { Q1A1: "Yes" })。
  3. Object.entries(cur):将当前问题子对象转换为一个键值对数组(例如 [['Q1A1', 'Yes']])。
  4. 内层 reduce:遍历这些键值对。accInner 是当前问题下的分数累加器,[key, val] 是当前的答案 ID 和其值。
  5. 条件判断 val !== 'No' && points[key]:
    • val !== 'No' 确保只有非 "No" 的答案才会被考虑。
    • points[key] 检查 points 对象中是否存在对应的答案 ID,并且它的值非零或非 undefined(尽管 points[key] 为 0 时 accInner + 0 不影响结果,但此检查通常用于确保键存在)。
  6. 如果条件为真,将 points[key] 的值加到 accInner。
  7. 最终,外层 reduce 返回所有问题分数的总和。

方法二:构建查找表并结合 filter 和 reduce

这种方法首先从 values 对象中创建一个简化的查找表,只包含需要计分的答案 ID。然后,利用这个查找表对 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. 构建一个查找表,只包含需要计分的答案ID
const lookup = Object.values(values).reduce((acc, cur) => {
  const [key, val] = Object.entries(cur)[0]; // 每个子对象只有一个键值对
  if (val === "Yes") { // 只将值为 "Yes" 的答案加入查找表
    acc[key] = true; // 可以是任何真值,这里用 true 表示存在
  }
  return acc;
}, {});

console.log("Lookup table:", lookup); // 输出: { Q1A1: true, Q2A1: true }

// 2. 遍历 points 对象,根据查找表过滤并求和
const totalPoints = Object.entries(points) // 获取 points 对象的所有键值对
  .filter(([key, score]) => lookup[key]) // 过滤:只保留在 lookup 表中存在的键
  .reduce((sum, [key, score]) => sum + score, 0); // 求和:累加过滤后的分数

console.log(totalPoints); // 输出: 60

解释:

  1. 构建 lookup 表:
    • Object.values(values).reduce(...) 遍历 values 对象。
    • 对于每个问题子对象,提取其唯一的键值对 [key, val]。
    • 如果 val 为 "Yes",则将 key 作为属性添加到 lookup 对象中,值为 true(或任何真值),表示该答案需要计分。
  2. 过滤并求和:
    • Object.entries(points) 将 points 对象转换为键值对数组。
    • filter(([key, score]) => lookup[key]):过滤掉那些键不在 lookup 表中的条目。只有 Q1A1 和 Q2A1 会通过过滤。
    • reduce((sum, [key, score]) => sum + score, 0):对过滤后的键值对进行求和,累加 score。

方法三:提取关键答案 ID 集合并使用 filter 和 reduce

如果 values 对象中答案的值(如 "Yes" / "No")不影响是否计分,而仅仅是键的存在决定是否计分,或者我们只需要收集所有选定的答案 ID,可以使用 Set 来存储这些键,从而提高查找效率。

const values = {
    Q1: { Q1A1: "Yes" },
    Q2: { Q2A1: "Yes" },
    Q3: { Q3A2: "No" }, // 这里的 "No" 依然会被提取键,如果逻辑需要
};

const points = {
    Q1A1: 41,
    Q1A2: 0,
    Q2A1: 19,
    Q2A2: 0,
    Q3A1: 25,
    Q3A2: 5,
};

// 1. 提取所有需要计分的答案ID到一个 Set 中
const selectedAnswerKeys = new Set(
  Object.values(values).map(question => Object.keys(question)[0])
);

console.log("Selected Answer Keys:", selectedAnswerKeys); // 输出: Set(3) { 'Q1A1', 'Q2A1', 'Q3A2' }

// 2. 遍历 points 对象,根据 Set 过滤并求和
const totalSum = Object.entries(points)
  .filter(([key, score]) => selectedAnswerKeys.has(key)) // 过滤:只保留在 Set 中存在的键
  .reduce((acc, [key, score]) => acc + score, 0); // 求和

console.log(totalSum); // 输出: 65 (因为 Q3A2 即使是 "No",其键也被提取并计分了 5)

注意: 此方法默认只要 values 对象中存在某个答案 ID,就将其计入总和,而不考虑其关联的 "Yes" / "No" 状态。如果需要考虑状态,应结合方法二的逻辑。

总结与注意事项

本文介绍了三种在 JavaScript 中根据键值比较两个对象并计算总和的方法:

  1. 嵌套 reduce: 适用于复杂的多层条件判断,但代码可能略显紧凑,可读性稍差。
  2. 构建查找表 + filter + reduce: 这种方法将逻辑分解为两个清晰的步骤(构建查找表和基于查找表过滤求和),通常更易于理解和维护,尤其当过滤条件涉及 values 对象中的具体值时(如 "Yes")。
  3. 提取键集合 + filter + reduce: 当仅关注键的存在性而忽略其关联值时,此方法简洁高效,利用 Set 进行快速查找。

选择建议:

  • 如果需要根据 values 对象中答案的具体值(如 "Yes" / "No")来决定是否计分,方法二(构建查找表)是最佳选择,它清晰地分离了条件判断和求和逻辑。
  • 如果 values 对象中的答案只要存在就计分(忽略其值),方法三(提取键集合)效率较高。
  • 方法一(嵌套 reduce)虽然功能强大,但在处理这种特定场景时,可能会牺牲一些可读性,但对于一次性完成所有操作的场景也很适用。

在实际开发中,请根据您的具体业务逻辑和团队的代码风格偏好来选择最合适的方法。同时,始终考虑代码的可读性、可维护性以及在处理大量数据时的性能表现。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

550

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

30

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

45

2026.01.06

undefined是什么
undefined是什么

undefined是代表一个值或变量不存在或未定义的状态。它可以作为默认值来判断一个变量是否已经被赋值,也可以用于设置默认参数值。尽管在不同的编程语言中,undefined可能具有不同的含义和用法,但理解undefined的概念可以帮助我们更好地理解和编写程序。本专题为大家提供undefined相关的各种文章、以及下载和课程。

6500

2023.07.31

网页undefined是什么意思
网页undefined是什么意思

网页undefined是指页面出现了未知错误的意思,提示undefined一般是在开发网站的时候定义不正确或是转换不正确,或是找不到定义才会提示undefined未定义这个错误。想了解更多的相关内容,可以阅读本专题下面的文章。

3344

2024.08.14

网页undefined啥意思
网页undefined啥意思

本专题整合了undefined相关内容,阅读下面的文章了解更多详细内容。后续继续更新。

1687

2025.12.25

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

37

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

136

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

47

2026.03.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号