如何高效实现JavaScript对象数组按type字段唯一值分组并生成指定统计结果数组
问题描述
我有一个对象数组,示例如下:
const data = [ {'name': 'apple', 'type': 'fruit', 'quantity': 5}, {'name': 'orange', 'type': 'fruit', 'quantity': 8}, {'name': 'broccoli', 'type': 'vegetable', 'quantity': 5}, ... ]
需求是:针对type字段的每一个唯一值,返回一个包含分组统计信息的结果数组,格式如下:
output = [ { 'field': 'fruit', 'count': 2, 'minQuantity': 5, 'maxQuantity': 8, 'values': ['apple', 'orange'] }, { 'field': 'vegetable', 'count': 1, 'minQuantity': 5, 'maxQuantity': 5, 'values': ['broccoli'] } ]
我目前尝试的代码只实现了部分功能,而且感觉效率不够高,代码如下:
let returnData = []; let fieldSet = new Set(data.map(a => a.type)); let fields = Array.from(fieldSet); for (var i = 0; i < fields.length; i++) { let objs = data.filter(obj => { return obj.type === fields[i] }) returnData.push({ field: fields[i], count: objs.length }) }
请问有没有简单且高效的实现方式可以完善需求?
解决方案
当然有!你当前的实现虽然能完成count的统计,但存在两个问题:一是没实现minQuantity、maxQuantity和values的需求;二是效率偏低——因为每次循环都要重新过滤整个数组,时间复杂度是O(n*m)(n是数据总长度,m是唯一type的数量),数据量大的时候性能会打折扣。
更高效的方式是只遍历一次数组,用Array.reduce()完成分组和所有统计逻辑,时间复杂度直接降到O(n),简单又高效。完整实现代码如下:
const data = [ {'name': 'apple', 'type': 'fruit', 'quantity': 5}, {'name': 'orange', 'type': 'fruit', 'quantity': 8}, {'name': 'broccoli', 'type': 'vegetable', 'quantity': 5}, // 可添加更多测试数据 ]; const output = Object.values(data.reduce((acc, item) => { // 若当前type未在累加器中,初始化分组结构 if (!acc[item.type]) { acc[item.type] = { field: item.type, count: 0, minQuantity: Infinity, // 初始设为无穷大,确保第一个元素能覆盖它 maxQuantity: -Infinity, // 初始设为负无穷,确保第一个元素能覆盖它 values: [] }; } // 更新当前分组的统计数据 const group = acc[item.type]; group.count++; group.minQuantity = Math.min(group.minQuantity, item.quantity); group.maxQuantity = Math.max(group.maxQuantity, item.quantity); group.values.push(item.name); return acc; }, {})); console.log(output);
代码逻辑解释:
reduce遍历与分组:用reduce遍历数组,累加器acc是一个以type为键的临时对象,用来存储每个分组的统计信息- 初始化分组结构:遇到新的
type时,初始化对应的分组对象,其中minQuantity和maxQuantity的初始值设置是关键——用无穷大/负无穷能确保第一个元素的数量正确成为初始的最小/最大值 - 更新统计数据:对每个元素,更新对应分组的计数、最小/最大数量,并将元素名称加入
values数组 - 转换为目标数组:最后用
Object.values()把临时对象的所有值提取出来,就得到了符合需求的结果数组
这种方式不仅代码更简洁,而且只需要遍历一次数据,在数据量较大时的性能优势会非常明显。
内容的提问来源于stack exchange,提问作者OJT
相关产品推荐
相关产品推荐

