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
andoccurance
against each year. firstValue
holds the first occurance value of that year.lastValue
holds the last occurance value of that year.label
year valueoccurance
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