游乐游手机版
首页/前端开发/文章详情

对象按属性值分组并统计频次的技巧

时间:2026-07-26 06:22
针对键为数字字符串的类数组对象,通过Object values提取记录,遍历按指定属性统计频次,利用??运算符确保初始值,最后用Object entries生成按插入顺序排列的数字索引格式结果。该方法简洁高效,兼容性好,无需外部库。
在实际开发中,我们经常遇到这样的需求:一个键值为对象的JavaScript对象,需要根据某个指定属性(如name)进行去重分组,并生成一个包含计数的新对象,同时输出结果保持数字索引顺序。这涉及几个关键知识点,下面逐步拆解分析。

在日常开发中,我们时常遇到这种场景:一个类似数组的对象,其键为连续的数字字符串,内部存储了多条记录。现在需要根据某个字段(例如 Name)来分组统计频次,即统计每个值出现的次数,最后以紧凑有序的格式重新组织数据。虽然输入的结构看起来像数组,但本质上仍是对象,无法直接使用 Array.prototype 的方法。必须先通过 Object.values() 提取所有值,这是必不可少的起点。

下面给出一个清晰高效且兼容性良好的实现方案:

const input = {
  0: { State: true, Name: 'bob' },
  1: { State: true, Name: 'candice' },
  2: { State: true, Name: 'allen' },
  3: { State: true, Name: 'bob' },
  4: { State: true, Name: 'bob' },
  5: { State: true, Name: 'candice' }
};

// 步骤 1:按 Name 统计频次(空值合并操作符 ?? 确保初始值为 0)
const countMap = {};
for (const { Name } of Object.values(input)) {
  countMap[Name] = (countMap[Name] ?? 0) + 1;
}

// 步骤 2:转换为按数字索引排列的目标格式
const result = {};
Object.entries(countMap).forEach(([Name, Count], index) => {
  result[index] = { Name, Count };
});

console.log(result);
// 输出:
// {
//   0: { Name: 'bob', Count: 3 },
//   1: { Name: 'candice', Count: 2 },
//   2: { Name: 'allen', Count: 1 }
// }

核心要点解析

  • 使用 Object.values(input) 提取所有值,这是最安全的方式,能有效避开原型链污染及非数字键的干扰。不要图省事直接遍历整个对象,那样容易引发问题。
  • ?? 0|| 0 更严谨。原因在于:如果 countMap[Name] 的值恰好为 0(虽然不常见,但逻辑上完全可能),|| 0 会将 0 视为假值而覆盖,而 ?? 仅在值为 undefinednull 时才会生效。细节决定成败,这个小坑值得留意。
  • Object.entries() 的输出顺序:它返回 [key, value] 数组,ES2015+ 规范明确保证了按插入顺序排列。因此示例中 'bob'、'candice'、'allen' 的顺序与它们首次出现的次序一致。如果业务需要按频次降序,则可在之后手动调用 .sort()
  • 最终结果使用数字字符串作为键(如 '0'、'1' 等),既满足原始需求,也便于后续当作类数组结构处理——例如使用 for...inObject.keys(result).map(...),都非常方便。

注意事项与优化建议

  • 输入对象的键如果不连续,例如混入了 '100'、'abc' 等键名,Object.values() 仍然不受影响,它只提取值,不关心键。但此时需明确业务逻辑是否依赖键的顺序,不可想当然。
  • 兼容性处理:若项目需支持 IE 浏览器,可将 ?? 替换为 countMap[Name] === undefined ? 0 : countMap[Name]。虽然代码稍显冗余,但稳定性更高。
  • 大数据量场景(万级以上),可考虑使用 Map 替代普通对象以提升插入与查找性能。但对于绝大多数日常场景,这种优化几乎无感知,切忌过度设计。

按照以上四步实现,代码简洁且可读性强,完全不依赖外部库,既使用了现代语法又保留了向后兼容性——这是解决JavaScript对象按属性值分组频次统计问题的理想方案。

来源:https://www.php.cn/faq/2782132.html
上一篇JS对象按字段值分组并统计频次的简洁实现 下一篇JavaScript深拷贝保留属性描述符的实现
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
CSS实现子元素在兄弟元素内视觉上嵌入并居中的方法
前端开发 · 2026-07-28

CSS实现子元素在兄弟元素内视觉上嵌入并居中的方法

本文详细解析如何借助 position: absolute 与相对定位上下文,让一个兄弟元素(如 c3)在视觉上“嵌入”并精确居中于另一个兄弟元素(如 c1)内部,同时兼容 flex-direction: column-reverse 布局模式。 在 CSS 布局的实际开发中,我们偶尔会遇到一个

JavaScript slice方法:身份证号出生日期精准提取
前端开发 · 2026-07-28

JavaScript slice方法:身份证号出生日期精准提取

处理身份证信息时,提取出生日期是个高频操作。很多人会下意识地想到正则表达式,但其实有个更简单直接的方法——字符串的 slice() 方法。它的优势在于,完全契合身份证号码的固定格式,无需复杂的模式匹配,就能精准、安全地拿到结果。 身份证号码的规则很明确:第7位到第14位这连续的8个字符,就是持证人的

纯JavaScript表单学生人数自动求和与金额计算
前端开发 · 2026-07-28

纯JavaScript表单学生人数自动求和与金额计算

表单里需要动态统计学生人数,再乘以单价自动算出总金额,这种需求在后台管理系统中非常普遍。但很多开发者习惯性写出的代码,往往隐藏着维护隐患:比如使用jQuery硬编码多个ID选择器,或者将计算逻辑与页面结构紧密耦合。 今天,我们就来解析一个更优雅的纯JavaScript方案。它不依赖任何外部库,借助事

如何用ESLint的HTML插件检查HTML内嵌脚本的代码质量
前端开发 · 2026-07-28

如何用ESLint的HTML插件检查HTML内嵌脚本的代码质量

你是否也遇到过这样的困扰:在VS Code中编写HTML时,标签里的JavaScript代码写得行云流水,但ESLint却毫无反应,连一个波浪线或错误提示都没有?别急着怀疑自己的代码完美无瑕,更可能是ESLint根本没对这部分内容进行检测。 问题的根源在于,ESLint默认只识别 js、 jsx这类

Vue 3 单文件组件动态加载的正确实践
前端开发 · 2026-07-28

Vue 3 单文件组件动态加载的正确实践

本文详细讲解如何在 Vue 3 中利用 defineAsyncComponent 与 vue3-sfc-loader 实现组件的响应式动态注册和渲染,从而避免因直接操作 DOM 或重复注册而引发的失效问题。 在 Vue 3 项目开发中,我们经常会遇到这样的需求:用户点击某个按钮后,才需要加载并渲染一