JavaScript如何将带时间戳的情感数据按30分钟区间实现多日聚合?
现有代码问题排查
- 聚合存储结构不合理:仅用两个全局数组存储聚合结果,切换日期时只重置了条目计数数组
nOfEntries,未重置情感值累加数组values,多日数据会叠加到同一数组中,最终只能得到最后一天的计算结果 - 日期切换判断逻辑失效:变量
createdDate和createdDateInit的声明存在作用域混乱问题,判断条件createdDateInit != createdDate无法正确识别日期切换 - 计算逻辑错误:代码中重复累加了两次
item.sentiment,导致最终平均值计算偏差 - 聚合粒度不符合需求:原有代码按1小时粒度聚合,未实现要求的30分钟区间聚合
修正后实现代码
function generateSentimentPoints(Sentiments) { // 用Map存储多日聚合数据,key为日期字符串,value为对应日期的聚合统计 const dateAggregateMap = new Map() // 每天共48个30分钟区间 const INTERVAL_PER_DAY = 48 Sentiments.forEach(item => { const time = new Date(item.created * 1000) // 生成统一格式的日期key,避免格式差异导致匹配失败 const dateKey = `${time.getFullYear()}/${time.getMonth()+1}/${time.getDate()}` // 计算当前时间所属的30分钟区间索引 const hour = time.getHours() const minute = time.getMinutes() const intervalIndex = hour * 2 + (minute >= 30 ? 1 : 0) // 首次处理当前日期时,初始化对应聚合容器 if (!dateAggregateMap.has(dateKey)) { dateAggregateMap.set(dateKey, { sumSentiment: new Array(INTERVAL_PER_DAY).fill(0), count: new Array(INTERVAL_PER_DAY).fill(0) }) } // 累加当前区间的情感值和条目计数 const currentAgg = dateAggregateMap.get(dateKey) currentAgg.sumSentiment[intervalIndex] += item.sentiment currentAgg.count[intervalIndex] += 1 }) // 生成最终结果,计算每个区间的平均情感值 const result = [] dateAggregateMap.forEach((agg, dateKey) => { const avgSentiment = agg.sumSentiment.map((sum, idx) => { return agg.count[idx] === 0 ? 0 : sum / agg.count[idx] }) result.push({ date: dateKey, // 30分钟区间平均情感值,索引0对应00:00-00:29、索引1对应00:30-00:59,以此类推 intervalAvgSentiment: avgSentiment }) }) return result }
功能说明
- 多日数据隔离:采用
Map结构按日期存储聚合数据,不同日期的计算结果完全独立,不会互相覆盖 - 30分钟区间适配:将一天划分为48个30分钟区间,通过时间计算匹配对应区间索引,满足聚合粒度要求
- 计算逻辑修正:去掉了重复累加的错误代码,计数从0开始统计,平均值计算准确
- 输出结果清晰:返回结果包含日期和对应日期所有30分钟区间的平均情感值,可直接使用,也可根据业务需求扩展magnitude的聚合逻辑
内容的提问来源于stack exchange,提问作者LeCoda
相关产品推荐
相关产品推荐

