如何在JavaScript中对同分类(cat)的JSON对象Quantity字段求和并生成唯一对象
你的实现完全正确,效率还拉满!
首先得给你点个赞——你写的代码完美实现了按cat分类求和quantity的需求,而且是**时间复杂度O(n)**的高效解法,只需要遍历一次原数组就能搞定。
咱们拆解下你的代码逻辑,看看为什么它能work:
- 用
data.reduce()搭配Map作为累加器:遍历数组时,以每个对象的cat作为Map的键,把对应的quantity累加起来(如果某个cat是第一次出现,就从0开始加) - 最后用
Array.from()把Map的键值对转换成你需要的对象数组格式
拿你的测试数据运行这段代码,输出结果正好是:
[{ cat: 'EK-1', quantity: 3 }, { cat: 'EK-2', quantity: 1 }]
完全符合预期!
这个方案还有个隐藏优势:Map的键支持任意类型,如果以后你的cat字段出现数字、对象这类非字符串值,代码也能正常运行,不会像普通对象那样出现键类型转换的问题。
可选的替代实现方案
如果想要更多选择,这里还有两种常用的写法,你可以根据场景挑选:
方案1:用普通对象替代Map(适合字符串类型的cat)
如果你的cat都是常规字符串(没有.、__proto__这类特殊字符),可以用普通对象做累加器,代码更直观:
const data = [{ cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-2', name: "test2", info: "nat", quantity: 1 }]; const products = Object.entries( data.reduce((acc, { cat, quantity }) => { acc[cat] = (acc[cat] || 0) + quantity; return acc; }, {}) ).map(([cat, quantity]) => ({ cat, quantity })); console.log(products);
缺点是如果cat有特殊字符,可能会和对象的内置属性冲突,这时候还是用你的原方案更安全。
方案2:先分组再求和(可读性优先)
如果团队里有人觉得reduce+Map的写法有点绕,也可以把逻辑拆成“分组→求和”两步,可读性更高:
const data = [{ cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-2', name: "test2", info: "nat", quantity: 1 }]; // 第一步:按cat分组 const groupedData = data.reduce((acc, item) => { acc[item.cat] = acc[item.cat] || []; acc[item.cat].push(item); return acc; }, {}); // 第二步:对每组的quantity求和 const products = Object.entries(groupedData).map(([cat, items]) => ({ cat, quantity: items.reduce((total, item) => total + item.quantity, 0) })); console.log(products);
这种写法逻辑更直白,但会多一次分组后的遍历(不过整体时间复杂度还是O(n),性能差异可以忽略),适合需要对分组后的数组做额外操作的场景。
总的来说,你的原实现已经是非常优秀的解法了,推荐继续使用!如果没有特殊需求,不用刻意更换方案~
内容的提问来源于stack exchange,提问作者kumar kumar




