javascript - 对按键分组的对象数组的值求和并返回到新的数组数组中
问题描述
我需要对按两个属性分组的所有值求和:"date"
和"zona"
. 特别是,我想翻译"date"
成星期几,并按它分组。我"zona"
想按“zona 1”、“zona 2”、“zona 3”等进行分组。
预期结果:
[dayOfWeek, zoneId, value];
[
[0, 0, something],
[0, 1, something],
...
[0, 9, something],
[1, 0, something],
...
[6, 9, something]
]
我已经做了类似的事情(jsfiddle here):
数据初始化:
const data = [
{
"date": "2017/12/31",
"ALL.new users": 298,
"ALL.returning users": 12528,
"zona 1.new users": 189,
"zona 1.returning users": 3422,
"zona 10.new users": 18,
"zona 10.returning users": 2767,
"zona 2.new users": 11,
"zona 2.returning users": 1216,
"zona 3.new users": 20,
"zona 3.returning users": 3175,
"zona 4.new users": 5,
"zona 4.returning users": 1465,
"zona 5.new users": 3,
"zona 5.returning users": 1102,
"zona 6.new users": 20,
"zona 6.returning users": 2223,
"zona 7.new users": 2,
"zona 7.returning users": 1063,
"zona 8.new users": 25,
"zona 8.returning users": 1093,
"zona 9.new users": 3,
"zona 9.returning users": 1507
}, {...}
];
const zoneMapping = {
"Zone 1": 0,
"Zone 2": 1,
"Zone 3": 2,
"Zone 4": 3,
"Zone 5": 4,
"Zone 6": 5,
"Zone 7": 6,
"Zone 8": 7,
"Zone 9": 8,
"Zone 10": 9
};
const dayMapping = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
功能:
let tempSeriesData = [];
data.forEach(
(item) => {
const date = (new Date(item.date)).getDay();
Object.entries(item).forEach(([key, value]) => {
if (key !== "date" && key !== "ALL.new users" && key !== "ALL.returning users" && !key.includes("new users")) {
let tempYValue = key.slice(0, 7).replace(".", "");
tempYValue = tempYValue.replace("a", "e");
const yValue = tempYValue.charAt(0).toLocaleUpperCase() + tempYValue.slice(1)
const dataValue = Number(value);
const element = [
date,
zoneMapping[yValue],
dataValue
];
const existingElement = tempSeriesData.find(el => el[0] === element[0] && el[1] === element[1]);
if (existingElement) {
existingElement[2] += element[2];
}
else {
tempSeriesData.push(element);
}
}
});
}
);
有了这个功能,我可以获得我想要的东西,但我正在寻找一种新的方法来做同样的事情,也许使用 map()、reduce 或其他东西,因为我想改进这些方法的使用。
提前感谢您的回答。
解决方案
其实没关系。代码是明确的,它做了它应该做的事情。如果我们真的想重构它,为了清楚起见,我会使用对象,然后稍后在数组中转换。另外我会使用 map/reduce 而不是全局 var + forEach 循环。
const parser = (item) => {
const date = (new Date(item.date)).getDay();
myItem = Object.entries(item).flatMap(([key, value]) => {
key = key.split(/[\s.]+/) // split the key on SPACE and DOT at the same time
// Maybe I misunderstand the IF from before but this works right now.
return key[2] === "returning" ? [{ day: date, zone: key[1] - 1, value: Number(value) }] : []
})
return myItem
}
// upsert adds elements to the object if new or update existing
const upSert = (acc, { value, ...r }) => {
key = JSON.stringify(r) // Since it is a nested map, we make our life easier with unique keys.
acc[key] = (acc[key] || { ...r, value: 0 }); // if null initialize
return (acc[key].value += value, acc) // update in place
}
const toValueArray = (data) => {
return Object.values(data).map(d => Object.values(d))
}
//This could be already populated from a previous run
// Probably comming as a prop to a component
seriesData = {}
myTs = data.flatMap(parser)
.reduce(upSert, seriesData)
const finalSeriesData = toValueArray(myTs)
推荐阅读
- javascript - 显示文件下载对话框时关闭当前弹出窗口
- webpack - 来自 webpack 的 DataCloneError
- spring-boot - 面对 java.lang.IllegalArgumentException: Not a managed type error in Spring boot
- angularjs - 如何使 ng-model 动态化?
- javascript - 将一个线对象拆分为多线对象
- css - 背景图像自动缩放
- perl - 如何在 Perl 中解析多行记录?
- java - Javafx 图表中的错误:添加了重复系列。为什么?
- .net - vb.net 3.5 - 在屏幕键盘上编写其他进程
- docker - 在安装在 docker 下的 nfs 上提供 http 内容