如何按天、1小时、6小时、8小时、周、月和年对日期和总和值数组进行分组?

2022-03-09 00:00:00 arrays date javascript lodash momentjs
我有日期数组,我想按年、月、周、日、6h、8h和1h以及总和对日期进行分组。例如,我有以下数组:

const data = [
  { x: "2021-10-17T14:38:45.540Z", y: 2 },
  { x: "2021-09-16T14:36:46.540Z", y: 1 },
  { x: "2021-01-04T14:35:46.540Z", y: 2 },
  { x: "2021-01-01T14:30:46.540Z", y: 1 },
  { x: "2020-02-01T06:28:47.520Z", y: 12 },
  { x: "2020-02-01T07:28:47.520Z", y: 12 },
  // ...
  { x: "2019-04-13T10:19:20.034Z", y: 20 },
  // ...
  { x: "2018-01-01T09:09:19.134Z", y: 4 },
  { x: "2017-01-01T12:09:19.034Z", y: 11 },
  { x: "2016-01-02T12:10:20.034Z", y: 24 },
  // ...
]

这就是我尝试使用的Momentjs和locashGroup array of object by date

对于年份,我得到了这样的结果,一些年份,如2018年和2016年,问题没有显示:

 [
  {
    "color": "Blue",
    "value": 6,
    "label": "2021"
  },
  {
    "color": "Blue",
    "value": 24,
    "label": "2020"
  },
  {
    "color": "Blue",
    "value": 1212,
    "label": "2019"
  },
  {
    "color": "Blue",
    "value": 11,
    "label": "2017"
  }
]

年度预期产量:

[
      {
        "color": "Blue",
        "value": 6,
        "label": "2021"
      },
      {
        "color": "Blue",
        "value": 24,
        "label": "2020"
      },
      {
        "color": "Blue",
        "value": 1212,
        "label": "2019"
      },
      {
        "color": "Blue",
        "value": 10,
        "label": "2018"
      },
      {
        "color": "Blue",
        "value": 11,
        "label": "2017"
      },
      {
        "color": "Blue",
        "value": 48,
        "label": "2016"
      }
    ]

解决方案

这可以通过使用Reduce的标准‘GROUP-BY’实现,此处使用Object.values()累加到对象并返回数组。

我已经声明了一个简单的get_date_parts帮助器来解析ISO日期字符串,该字符串应该足够用于分组,但是如果需要,您可以将Date对象用于更复杂的标签格式。

以下是年份分组,该模式可以适用于您的所有其他分组,不过您需要进行一些运算才能确定小时范围。

const data = [{ x: '2021-10-17T14:38:45.540Z', y: 2 }, { x: '2021-09-16T14:36:46.540Z', y: 1 }, { x: '2021-01-04T14:35:46.540Z', y: 2 }, { x: '2021-01-01T14:30:46.540Z', y: 1 }, { x: '2020-02-01T06:28:47.520Z', y: 12 }, { x: '2020-02-01T07:28:47.520Z', y: 12 }, { x: '2019-04-13T10:19:20.034Z', y: 20 }, { x: '2018-01-01T09:09:19.134Z', y: 4 }, { x: '2017-01-01T12:09:19.034Z', y: 11 }, { x: '2016-01-02T12:10:20.034Z', y: 24 },];

function get_date_parts(iso_string) {
  const [year, month, day, hr, min, sec] = iso_string.split(/D/g);

  return { year, month, day, hr, min, sec };
}

function group_by_year(arr) {
  return Object.values(
    arr.reduce((a, { x: date_string, y: value }) => {
      const { year } = get_date_parts(date_string);
      (a[year] ??= { color: 'Blue?', value: 0, label: year }).value += value;

      return a;
    }, {}),
  );
}

const grouped_by_year = group_by_year(data).sort((a, b) => +b.label - +a.label);

console.log(grouped_by_year);

或按月,还显示logical nullish assignment (??=)的替代选项,用于初始分配给a[key]

const data = [{ x: '2021-10-17T14:38:45.540Z', y: 2 }, { x: '2021-09-16T14:36:46.540Z', y: 1 }, { x: '2021-01-04T14:35:46.540Z', y: 2 }, { x: '2021-01-01T14:30:46.540Z', y: 1 }, { x: '2020-02-01T06:28:47.520Z', y: 12 }, { x: '2020-02-01T07:28:47.520Z', y: 12 }, { x: '2019-04-13T10:19:20.034Z', y: 20 }, { x: '2018-01-01T09:09:19.134Z', y: 4 }, { x: '2017-01-01T12:09:19.034Z', y: 11 }, { x: '2016-01-02T12:10:20.034Z', y: 24 },];

function get_date_parts(iso_string) {
  const [year, month, day, hr, min, sec] = iso_string.split(/D/g);

  return { year, month, day, hr, min, sec };
}

function group_by_month(arr) {
  return Object.values(
    arr.reduce((a, { x: date_string, y: value }) => {
      const { year, month } = get_date_parts(date_string);
      const key = `${year}/${month}`;
      // using logical nullish assignment
      //(a[key] ??= { color: 'Blue?', value: 0, label: key }).value += value;

      // or written out long hand
      if (a[key] === undefined) {
        a[key] = { color: 'Blue?', value: 0, label: key };
      }

      a[key].value += value;

      return a;
    }, {}),
  );
}

const grouped_by_month = group_by_month(data).sort((a, b) => b.label.localeCompare(a.label));

console.log(grouped_by_month);

对于未在日期中直接表示的分组,您可以使用一些简单的算法。

function get_date_parts(iso_string) {
  const [year, month, day, hr, min, sec] = iso_string.split(/D/g);

  return { year, month, day, hr, min, sec };
}

const date_string = '2020-02-07T07:28:47.520Z';

const { year, month, day, hr } = get_date_parts(date_string);

// week in the month
const week = Math.floor((parseInt(day, 10) - 1) / 7);
const week_label = `${year}/${month} - week ${week + 1}`;
console.log({ week_label, week });

// hour range
const range_size = 8;
const range = Math.floor(parseInt(hr, 10) / range_size);
// range times
const range_start = `${(range * range_size).toString().padStart(2, '0')}:00`;
const range_end = `${(range * range_size + range_size).toString().padStart(2, '0')}:00`;
const range_label = `${day}/${month}/${year} ${range_start}-${range_end}`;

console.log({ range_label, range });

相关文章