减少数组数组,按日期将数据连接到周数据并对值求和
Reduce array of arrays, concat data by dates to week data and sum the values
所以我有一组奇特的数据:
data: [
['2022-01-17T16:29:24', 30], // these below would aggregate to 210
['2022-01-17T17:37:24', 30],
['2022-01-17T17:41:40', 30],
['2022-01-17T17:41:48', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:29', 30],
['2022-01-12T12:50:18', 30], // these below would aggregate to 90
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:29', 30]
]
我需要将其缩减为周数据集。我会将日期转换为一周的开始以获取周数据 moment(day).startOf('isoWeek')
,然后将类似日期的数据合并并将其减少为单个条目。
最终结果如下:
data: [
['2022-01-17T00:00:00', 210],
['2022-01-10T00:00:00', 90]
]
但我正在寻找如何使用 .reduce()
或任何其他更现代的解决方案的建议,这些解决方案将在大型集上表现出色。现在我已经为此嵌套了 for 循环(除了看起来很糟糕)可能表现很差,因为它在同一个数组上迭代多次。一个要求是 moment
应该用于日期操作,请尽量避免 Date
对象。
现在我有这样的东西:
mergeDataToWeek(data: any[]) {
let reducedArrays = [];
for (let arr of data) {
if (moment(arr[0]).isValid() && arr[1] > 0) {
arr[0] = moment(arr[0]).startOf('isoWeek').toISOString(true);
if (!reducedArrays.some(reduced => reduced[0] == (arr[0]))) {
reducedArrays.push(arr);
} else {
let target = reducedArrays.find(reduced => reduced[0] == arr[0]);
target[1] += arr[1];
}
}
}
console.log(reducedArrays);
return reducedArrays;
}
我正在尝试使用 reduce 解决它,但结果将是一个对象。像这样:
const moment = require("moment")
var x = [
['2022-01-17T16:29:24', 30],
['2022-01-17T17:37:24', 30],
['2022-01-17T17:41:40', 30],
['2022-01-17T17:41:48', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:29', 30],
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:29', 30]
]
// solution
var y = x.reduce((a,b) => {
const key = moment(b[0]).startOf("isoWeek").format()
a[key] = a[key]? a[key]+b[1]: b[1]
return a
}, {})
console.log(y)
输出:
{
"2022-01-17T00:00:00+07:00": 210,
"2022-01-10T00:00:00+07:00": 90
}
但如果您希望它像您的数组一样,我们可以通过以下方式转换它:
var z = Object.keys(y).map(i => [i,y[i]])
// OR THIS -- Thanks to @ghybs
var z = Object.entries(y)
console.log(z)
输出:
[
[ '2022-01-17T00:00:00+07:00', 210 ],
[ '2022-01-10T00:00:00+07:00', 90 ]
]
虽然这不是最好的解决方案,但我认为它比嵌套循环更具可读性。
运行 代码
let x = [
['2022-01-17T16:29:24', 30],
['2022-01-17T17:37:24', 30],
['2022-01-17T17:41:40', 30],
['2022-01-17T17:41:48', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:29', 30],
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:29', 30]
]
// solution
const groupedTotal = x.reduce((a, b) => {
const key = moment(b[0]).startOf("isoWeek").format()
a[key] = a[key] ? a[key] + b[1] : b[1]
return a
}, {});
const totals = Object.entries(groupedTotal);
console.log("Grouped Total:", groupedTotal, "\n Totals:", totals);
<script src="https://unpkg.com/moment@2.29.1/moment.js"></script>
注意:- 来自@Rizal Ardhi Rahmadani 的代码...
所以我有一组奇特的数据:
data: [
['2022-01-17T16:29:24', 30], // these below would aggregate to 210
['2022-01-17T17:37:24', 30],
['2022-01-17T17:41:40', 30],
['2022-01-17T17:41:48', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:29', 30],
['2022-01-12T12:50:18', 30], // these below would aggregate to 90
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:29', 30]
]
我需要将其缩减为周数据集。我会将日期转换为一周的开始以获取周数据 moment(day).startOf('isoWeek')
,然后将类似日期的数据合并并将其减少为单个条目。
最终结果如下:
data: [
['2022-01-17T00:00:00', 210],
['2022-01-10T00:00:00', 90]
]
但我正在寻找如何使用 .reduce()
或任何其他更现代的解决方案的建议,这些解决方案将在大型集上表现出色。现在我已经为此嵌套了 for 循环(除了看起来很糟糕)可能表现很差,因为它在同一个数组上迭代多次。一个要求是 moment
应该用于日期操作,请尽量避免 Date
对象。
现在我有这样的东西:
mergeDataToWeek(data: any[]) {
let reducedArrays = [];
for (let arr of data) {
if (moment(arr[0]).isValid() && arr[1] > 0) {
arr[0] = moment(arr[0]).startOf('isoWeek').toISOString(true);
if (!reducedArrays.some(reduced => reduced[0] == (arr[0]))) {
reducedArrays.push(arr);
} else {
let target = reducedArrays.find(reduced => reduced[0] == arr[0]);
target[1] += arr[1];
}
}
}
console.log(reducedArrays);
return reducedArrays;
}
我正在尝试使用 reduce 解决它,但结果将是一个对象。像这样:
const moment = require("moment")
var x = [
['2022-01-17T16:29:24', 30],
['2022-01-17T17:37:24', 30],
['2022-01-17T17:41:40', 30],
['2022-01-17T17:41:48', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:29', 30],
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:29', 30]
]
// solution
var y = x.reduce((a,b) => {
const key = moment(b[0]).startOf("isoWeek").format()
a[key] = a[key]? a[key]+b[1]: b[1]
return a
}, {})
console.log(y)
输出:
{
"2022-01-17T00:00:00+07:00": 210,
"2022-01-10T00:00:00+07:00": 90
}
但如果您希望它像您的数组一样,我们可以通过以下方式转换它:
var z = Object.keys(y).map(i => [i,y[i]])
// OR THIS -- Thanks to @ghybs
var z = Object.entries(y)
console.log(z)
输出:
[
[ '2022-01-17T00:00:00+07:00', 210 ],
[ '2022-01-10T00:00:00+07:00', 90 ]
]
虽然这不是最好的解决方案,但我认为它比嵌套循环更具可读性。
运行 代码
let x = [
['2022-01-17T16:29:24', 30],
['2022-01-17T17:37:24', 30],
['2022-01-17T17:41:40', 30],
['2022-01-17T17:41:48', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:18', 30],
['2022-01-21T12:50:29', 30],
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:18', 30],
['2022-01-12T12:50:29', 30]
]
// solution
const groupedTotal = x.reduce((a, b) => {
const key = moment(b[0]).startOf("isoWeek").format()
a[key] = a[key] ? a[key] + b[1] : b[1]
return a
}, {});
const totals = Object.entries(groupedTotal);
console.log("Grouped Total:", groupedTotal, "\n Totals:", totals);
<script src="https://unpkg.com/moment@2.29.1/moment.js"></script>
注意:- 来自@Rizal Ardhi Rahmadani 的代码...