求助:JavaScript数组reduce统计设备故障次数出错及优化方案
设备故障统计Reduce代码问题排查与优化
需求说明
获取一组包含StationID、Working、Failed、DeviceCreatedDate字段的设备状态数据,需按唯一StationID(对应示例中的user字段)统计各Failed故障类型的出现次数,输出格式参考infoReduced示例。当前编写的reduce统计代码无法正确累加次数,输出不符合预期,现排查问题并提供简洁实现方案。
原始数据示例
const rawData = [ { StationID: "user1", Failed: "ErrorA", Working: true, DeviceCreatedDate: "2024-01-01" }, { StationID: "user1", Failed: "ErrorB", Working: false, DeviceCreatedDate: "2024-01-02" }, { StationID: "user1", Failed: "ErrorA", Working: false, DeviceCreatedDate: "2024-01-03" }, { StationID: "user2", Failed: "ErrorC", Working: false, DeviceCreatedDate: "2024-01-01" }, { StationID: "user2", Failed: "ErrorA", Working: false, DeviceCreatedDate: "2024-01-02" } ];
期望输出(infoReduced示例)
const infoReduced = { "user1": { "ErrorA": 2, "ErrorB": 1 }, "user2": { "ErrorC": 1, "ErrorA": 1 } };
当前错误代码示例
// 常见错误实现:每次覆盖用户的故障统计对象 const wrongResult = rawData.reduce((acc, curr) => { const station = curr.StationID; const error = curr.Failed; // 错误:直接赋值新对象,覆盖原有统计数据 acc[station] = { [error]: (acc[station]?.[error] || 0) + 1 }; return acc; }, {});
当前错误输出
{ "user1": { "ErrorA": 1 }, "user2": { "ErrorA": 1 } }
问题原因
错误代码中,每次处理数据时都会直接给acc[station]赋值一个新对象,覆盖了该StationID下之前已统计的所有故障类型数据,最终仅保留最后一次处理的故障类型及次数,无法实现累加效果。
简洁优化实现方案
方案1:Reduce直接累加(最直观)
const correctResult = rawData.reduce((acc, { StationID: user, Failed: error }) => { // 初始化用户对应的故障统计对象(不存在则创建) if (!acc[user]) { acc[user] = {}; } // 累加故障次数:存在则+1,不存在则初始化为1 acc[user][error] = (acc[user][error] || 0) + 1; return acc; }, {});
方案2:ES6扩展运算符简化写法
const correctResult = rawData.reduce((acc, curr) => { const { StationID: user, Failed: error } = curr; // 扩展原有对象,更新对应故障的次数,避免覆盖 acc[user] = { ...acc[user], [error]: (acc[user]?.[error] || 0) + 1 }; return acc; }, {});
方案3:Map结构实现(适合复杂场景扩展)
const stationMap = new Map(); rawData.forEach(({ StationID: user, Failed: error }) => { // 初始化用户的故障统计Map if (!stationMap.has(user)) { stationMap.set(user, new Map()); } const errorMap = stationMap.get(user); // 累加故障次数 errorMap.set(error, (errorMap.get(error) || 0) + 1); }); // 转换为目标对象格式 const correctResult = Object.fromEntries( Array.from(stationMap.entries()).map(([user, errorMap]) => [ user, Object.fromEntries(errorMap.entries()) ]) );
内容的提问来源于stack exchange,提问作者Ezequiel Diaz
相关产品推荐
相关产品推荐

