如何按年份对日期数组进行分组并减去最后一个值 - 第一个值?

How to group array of dates by year and subtract last value - first value?

我有日期数组,我想按年份对日期进行分组并减去最后一个值 - 第一个值。例如,我有以下数组:

const data = [
  { x: "2021-10-17T14:38:45.540Z", y: 2 },
  { x: "2021-10-17T13: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 },
  { x: "2016-01-02T11:10:20.034Z", y: 14 }
];

这是我试过的Group array of object by year and subtract the last value - the first value

我得到了对值求和的结果:

 [
  {
    "value": 8,
    "label": "2021"
  },
  {
    "value": 24,
    "label": "2020"
  },
  {
    "value": 20,
    "label": "2019"
  },
  {
    "value": 4,
    "label": "2018"
  },
  {
    "value": 11,
    "label": "2017"
  },
  {
    "value": 38,
    "label": "2016"
  }
]

年的预期产出(值 = 最后一个值 - 第一个值):

 [
  {
    "value": 1,
    "label": "2021"
  },
  {
    "value": 0,
    "label": "2020"
  },
  {
    "value": 20,
    "label": "2019"
  },
  {
    "value": 4,
    "label": "2018"
  },
  {
    "value": 11,
    "label": "2017"
  },
  {
    "value": 10,
    "label": "2016"
  }
]

这是按年份分组的函数:

function group_by_year(arr) {
  return Object.values(
    arr.reduce((a, { x: date_string, y: value }) => {
      const { year } = get_date_parts(date_string);
      if (a[year] === undefined) {
        a[year] = { value: 0, label: year };
      }
      a[year].value += value; // the problem (lastValue - firstValue)

      return a;
    }, {})
  );
}

问题是如何将这一行 a[year].value += value; 更改为 a[year].value = lastValue - firstValue;

使用 moment 库,您可以将日期字符串提取到年份中 moment("2021-10-17T14:38:45.540Z").format('YYYY') 准备好数组对象后,您可以简单地对数组进行排序并找到答案

在这里你必须将同年数据的数组单独分组,然后第一个和最后一个索引可以简单地在 for 循环中找到

在累加器内部,您只是将数组中的值相加。这将产生一年的总价值。

我使用了下面的逻辑。

  • 每年保持 firstValuelastValuelabeloccurance
  • firstValue 保存当年的第一个出现值。
  • lastValue 保存那一年的最后一次出现值。
  • label 年值
  • occurance 数组中每年的计数。

Array.reduce、运行 Array.map 获得的累积结果生成您想要的输出。它将是 lastValue - firstValue。如果您只对无符号的正差感兴趣,请使用 Math.abs

工作Fiddle

const data = [{ x: "2021-10-17T14:38:45.540Z", y: 2 },{ x: "2021-10-17T13: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 },{ x: "2016-01-02T11:10:20.034Z", y: 14 }];

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) {
  const grouppedYear = Object.values(
    arr.reduce((a, { x: date_string, y: value }) => {
      const { year } = get_date_parts(date_string);
      if (a[year] === undefined) {
        a[year] = {
          firstValue: value,
          lastValue: value,
          label: year,
          occurance: 1,
        };
      } else {
        a[year].lastValue = value;
        ++a[year].occurance;
      }
      return a;
    }, {})
  );
  const returnValue = grouppedYear.map(({firstValue, lastValue, label, occurance}) => ({value: occurance > 1 ? lastValue - firstValue : firstValue, label}))
  return returnValue;
}
const output = group_by_year(data);
console.log(output)