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

Time:10-27

I have the array of dates and I want to group dates by year and subtract the last value - the first value. for example, I have the following array:

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 }
];

This is what I tried Group array of object by year and subtract the last value - the first value

I got this result which sum the values :

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

Expected output for year (value = last value - first value):

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

This is the group by year function :

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;
    }, {})
  );
}

The problem is how to change this line a[year].value = value; to a[year].value = lastValue - firstValue;

CodePudding user response:

Inside the accumulator, you are just adding the values from array. This will generate total value against an year.

I have used the below logic.

  • Kept the firstValue, lastValue, label and occurance against each year.
  • firstValue holds the first occurance value of that year.
  • lastValue holds the last occurance value of that year.
  • label year value
  • occurance count of each year in the array.

From the Accumulated result obtained from Array.reduce, run Array.map to generate the output of your desire. It will be lastValue - firstValue. Use Math.abs if you are interested in positive difference only without sign.

Working 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)
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

using moment library you can extract date string into year moment("2021-10-17T14:38:45.540Z").format('YYYY') after preparing object of array you can simply sort the array and find the answer

here you have to make separate group of array of same year data and then first and last index can simply find in for loop

  • Related