减少数组数组,按日期将数据连接到周数据并对值求和

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 的代码...