新闻中心

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

2025-12-05
浏览次数:
返回列表

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

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

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

场景描述与数据结构

假设我们有以下两个 J*aScript 对象:

  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。

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

方法一:使用嵌套的 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

解释:

  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 对象进行过滤和求和。这种方法通常更易于阅读和理解。

拾贝 拾贝

一键同步微信读书所有笔记和划线,并在新标签页回顾

拾贝 186 查看详情 拾贝
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" 状态。如果需要考虑状态,应结合方法二的逻辑。

总结与注意事项

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

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

选择建议:

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

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

以上就是如何在 J*aScript 中根据键值比较两个对象并计算总和的详细内容,更多请关注其它相关文章!


# 这种方法  # 陕西seo查询打造公司  # 上城区seo网站优化  # 什么网站优化软件最好用  # seo里面 快照是什么  # 怎样搜网站关键词优化  # 推广营销的两个极端是  # 宜兴搜索营销推广  # 河北推广网站维护业务  # 招商加盟品牌推广营销  # 药店营销推广计划怎么写  # 如何在  # javascript  # 转换为  # 拾贝  # 累加器  # 数据结构  # 值为  # 象中  # 遍历  # 键值  # red  # 键值对  # java 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: Golang如何使用context实现超时取消_Golang context超时取消模式实践  Python异步编程实践:使用Binance API构建实时交易数据流  邮政快递包裹最新位置 邮政快递实时追踪入口  EMS快递官网app_中国邮政速递物流手机客户端  小红书怎么解除第三方平台绑定_小红书多平台登录解绑方法介绍  探索高级语言到原生C/C++的转译:挑战与内存管理策略  KFC早餐时段怎么领特惠代码_KFC早餐订餐优惠代码获取与使用说明  如何解决电商平台定制报价请求的“黑洞”问题,SprykerQuoteRequest模块助你提升客户体验与销售效率  J*aScript map 迭代中检测空数组元素的有效方法  wps文字怎么插入目录并自动更新_wps文字如何插入目录并自动更新方法  UC浏览器网页版登录入口官网 电脑版网址入口  Steam官网入口直达 Steam注册及登录步骤  Centos/Linux 系统下安装 composer 的完整步骤  Golang如何使用buffered channel提高性能_Golang buffered channel优化技巧  蛙漫官网漫画入口地址_蛙漫在线畅读无广告弹窗  Excel Power Pivot如何处理XML数据源 构建高级数据模型  MAC的“快捷指令”怎么同步到iPhone_MAC利用iCloud同步所有设备的自动化指令  mysql备份恢复性能优化_mysql备份恢复性能优化方法  Go RPC HTTP服务正确实现与常见陷阱解析  J*a递归快速排序中静态变量导致数据累积问题的解决方案  优化HTML表单样式:解决输入框焦点跳动与元素间距问题  4399网页游戏电脑版全新入口 4399电脑端在线玩指南  Python实现多节点属性重叠度分析教程  Win11怎么用U盘重装系统 Win11制作启动盘并重装系统完整教程【详解】  vivo浏览器自带的下载器速度慢怎么办 vivo浏览器提升文件下载速度的技巧  百度浏览器字体显示异常偏小_百度浏览器字体渲染修复方案  Win10磁盘清理工具在哪 Win10打开并使用磁盘清理【教程】  一加Ace 6T支持全新明眸护眼:通过了最严苛的护眼小金标认证  Angular响应式表单:实现提交后表单及按钮的禁用与只读化  漫蛙漫画网页端入口 漫蛙2官方正版漫画站点  我的世界mc.js免费游戏直接能玩 我的世界mc.js小游戏免费秒玩入口  深入理解J*aScript Promise异步执行与微任务队列  css滚动区域卡顿如何改善_css滚动问题用will-change优化渲染  C++如何解决segmentation fault_C++段错误调试与原因分析  Golang如何安装Swagger工具_GoSwagger文档生成环境  优化 Python 函数中的条件逻辑:解决 if-else 嵌套与参数选择问题  AngularJS $http POST请求数据传递与Go后端接收实践  漫蛙漫画官方主页入口 漫蛙MANWA网页直达访问链接  CSS实现侧边栏导航项全宽圆角悬停背景效果  使用CSS更改登录屏幕输入框中PNG图标颜色的策略与局限性  CSS子选择器:如何区分并样式化嵌套列表的子层级  TikTok搜索不到用户发布内容怎么办 TikTok用户内容搜索优化方法  Lar*el 8 多关键词数据库搜索优化实践  Lar*el如何生成PDF或Excel文件_Lar*el文档导出工具与使用教程  解决移动端滚动问题的overflow属性应用指南  漫蛙漫画登录站点 漫蛙2正版漫画快速访问  京东单号查询入口_京东快递订单追踪入口  J*aScript异步迭代器_j*ascript异步遍历  优化MinIO list_objects_v2 操作的性能瓶颈与最佳实践  虚幻5科幻题材ARPG大作遭取消!本是《奇异人生》厂商新作 

搜索