本文详解JavaScript中利用groupBy函数实现数组数据聚合的方法。通过定义分组函数,将对象数组按指定属性值归类,并结合sortData进行排序。文中对比了ES5与ES6箭头函数的写法,并展示了如何修改逻辑以保留每个分组内的最新多条数据,适用于时序数据库等场景。
前言
本文旨在探讨如何在JavaScript端处理时序数据库(TSDB)数据,具体需求是将相同类型的数据归类在一起,并提取同一时间段内的最新数据。这种处理方式在概念上被称为数据聚合,即根据数据的特定属性进行计算和归类。
一、数据聚合
1. groupBy()函数
实现聚合功能主要依赖groupBy函数,该函数接收两个参数:一个是待处理的对象数组,另一个是匿名函数。该匿名函数的作用是提取对象中指定属性的值,并将具有相同属性值的对象归入同一个数组中。
groupBy: function(array, func){
var groups = {};
array.forEach(function(element){
var group = JSON.stringify(func(element));
groups[group] = groups[group] || []; //第一次执行为空数组
//groups[group] = [] //这样写就会覆盖之前的数据,视情况而用
groups[group].push([element,group]);//这里可以单独传element,本人是需要用到group才需要进行push
});
return Object.keys(groups).map(function(group){
return groups[group];
});
},上述实现返回的是一个数组结构。若需直接获取key对应的具体数组内容,可进一步处理。
return Object.keys(groups).map(function(group){
return groups[group];
});利用Object.keys(groups)可以提取groups对象中的所有键名,随后遍历这些键名组成的新数组,最终返回一个经过分组的二维数组结构。
- 在groupBy函数的内部实现中,首先初始化一个空对象用于存储分组结果。
- 接着使用forEach方法遍历传入的对象数组,遍历回调函数仅接收一个参数element,代表数组中的每一个元素。
- 由于分组依据是name属性,代码中通过let group = JSON.stringify(func(element))来获取用于排序或分组的属性值。例如,这里使用new Date(item.timestamp * 1000).getHours()将时间戳转换为小时数,作为分组的依据,并将其转换为JSON字符串以确保键名的唯一性。
- 执行groups[group] = groups[group] || []这行代码时,利用了JavaScript对象作为关联数组的特性。这一步骤完成了两件事:一是将group字符串作为groups对象的键,二是初始化对应的值为空数组。在首次执行时,该值为空数组;在后续循环中,若遇到相同的name值,则保持该数组引用不变。
- 值得注意的是,若将上述代码简化为groups[group] = [],则每次push操作都会覆盖之前的数据。这种写法适用于只需获取同一时间段内最新一条数据的场景。
- groups[group].push([element, group])这行代码的作用是将当前遍历到的对象element以及对应的group标识作为数组元素压入分组数组中,作为该分组的值。
2. sortData()函数
定义好groupBy函数后,即可调用该函数进行数据排序处理。
sortData: function(Data){
var sorted = this.groupBy(Data, function(item){
return new Date(item.timestamp * 1000).getHours(); // 返回需要分组的对象
// return item.name; // 返回需要分组的对象
});
return sorted;
},在sortData函数的return语句中,可以返回数组参数进行比较,例如通过item中的name属性进行排序。这里的item即为groupBy函数func(element)中传入的element对象。
二、ES6箭头函数写法
上述示例使用的是ES5语法。在ES6标准引入后,JavaScript提供了箭头函数,使得代码更加简洁。以下是使用ES6箭头函数重写的实现方式。
1. sortClass()函数
sortClass(Data){
const groupBy = (array, func) => {
let groups = {};
array.forEach((element)=>{
let group = JSON.stringify(func(element));
groups[group] = groups[group] || [];
groups[group].push(element);
});
return Object.keys(groups).map((group) =>{
return groups[group];
})
};
const sorted = groupBy(Data, (item) =>{
return item.name;
})
return sorted;
}2. 运行结果

调用sortClass(res.query)后得到的结果如上所示。本文示例中通过timestamp时间戳进行排序,红框中标注的数据即为push[element, group]操作中的group部分。
三、按需聚合(结合实际使用)
前文示例中,数据聚合后每个key对应的数组仅包含当前最新的值(即一条数据)。如果业务需求要求保留每个key对应的最新两条数据,则需要对groupBy函数进行相应调整。
1. groupBy()函数
/**
* author: CSH
* 函数功能:给定参数对数组进行分组并排序
* @param {Object} array [需要排序的数组]
* @param {Object} func [该函数参数用于返回用于分组排序的对象]
*/
groupBy: function(array, func){
var groups = {};
array.forEach(function(element){
var group = JSON.stringify(func(element));
groups[group] = groups[group] || []; //第一次执行为空数组
// groups[group] = []; // 这样就能得到当前小时时间段内最新的数据
groups[group].push([element,group]);
groups[group].length >= 3 ? groups[group].shift() : null; // 只保留当前数组最新两组数据
});
return Object.keys(groups).map(function(group){
return groups[group];
});
},在JavaScript中,若要在数组中仅保留最新两项数据,可以使用数组的shift()方法。该方法用于移除并返回数组的第一个元素,同时将所有其他元素“位移”到更低的索引位置,其行为类似于队列。通过调用该方法,可以确保数组内始终只保留最新的两项数据。
2. sortData()函数(无改动)
/**
* author: CSH
* 函数功能:给定数组,并返回需要分组的对象,然后根据该对象进行分组排序返回新的数组
* @param {Object} sortData [需要数据聚合的数组]
*/
sortClass: function(sortData){
var sorted = this.groupBy(sortData, function(item){
return new Date(item.timestamp * 1000).getHours(); // 返回需要分组的对象
// return item.name; // 返回需要分组的对象
});
return sorted;
},在对groupBy()函数进行上述修改后,再次调用sortData函数即可返回符合“保留最新两项数据”要求的结果。
总结
以上内容介绍了JavaScript中数据聚合的基本方法,并分别展示了ES5和ES6两种语法下的实现写法。
至此,关于JavaScript数组中相同元素进行分组(数据聚合)的groupBy函数详解已完成。如需了解更多关于js数组分组及groupBy函数的内容,请搜索本站历史文章或浏览后续相关文章,感谢支持。