I have data in an array which has a structure like this
[
{createdAt: "2022-03-12T13:15:41.844+00:00", "name": 'adipiscing'},
{createdAt: "2022-03-04T11:56:27.545+00:00", "name": 'consectetur'},
{createdAt: "2021-01-15T09:12:25.418+00:00", "name": 'amet'},
{createdAt: "2021-01-09T09:12:25.418+00:00", "name": 'sit'},
{createdAt: "2021-01-02T08:52:55.418+00:00", "name": 'dolor'},
{createdAt: "2021-12-15T09:12:25.418+00:00", "name": 'ipsum'},
{createdAt: "2021-12-11T08:52:55.418+00:00", "name": 'lorem'},
]
The data above is sorted in desc by createdAt.
Currently for numbering I use the index data as usual, I want to change the numbering based on the createdAt column but at every change of month or entry in a new month or year, the number resets to 1 again
Can anyone help me, I'm very grateful.
The below may be one possible solution to achieve the desired objective:
Code Snippet
// helper method to get either YYYY-MM (if full=false) or YYYY-MM-DD (otherwise)
const getDtYMD = (dt, full = false) => (
full ? dt.createdAt.split('T')[0] : dt.slice(0, 7)
);
// transform the arr to add a group-id (idGroup)
const sortAndGroup = arr => (
Object.values( // get the values of the result object
[...arr.map(x => ({...x}))].sort( // first sort the input-array reverse-chronological order (latest date at 0)
(a, b) => (getDtYMD(a, true) > getDtYMD(b, true) ? 1 : -1)
).reduce( // use .reduce to iterate over the sorted array
(acc, {createdAt : c, name}) => ({
...acc, // safe-keep existing accumulator object
[getDtYMD(c)]: ([
...(acc[getDtYMD(c)] || []),
{ // append new object to value array for key YYYY-MM
idGroup: (acc[getDtYMD(c)]?.length || 0) + 1,
createdAt: c, // update 'idGroup' based on existing value-array's length
name
}
])
}),
{}
)
).flat().sort(
(a, b) => (
getDtYMD(a, true) > getDtYMD(b, true)
? -1
: getDtYMD(a, true) < getDtYMD(b, true)
? 1
: a.idGroup > b.idGroup ? -1 : 1
)
)
);
const unsortedRawDataArray = [
{'createdAt': "2022-03-12T13:15:41.844+00:00", "name": '1 adipiscing'},
{'createdAt': "2022-03-04T11:56:27.545+00:00", "name": '1 consectetur'},
{'createdAt': "2022-03-04T11:56:27.545+00:00", "name": '2 consectetur'},
{'createdAt': "2022-03-04T11:56:27.545+00:00", "name": '3 consectetur'},
{'createdAt': "2021-01-15T09:12:25.418+00:00", "name": '1 amet'},
{'createdAt': "2021-01-09T09:12:25.418+00:00", "name": '1 sit'},
{'createdAt': "2021-01-09T09:12:25.418+00:00", "name": '2 sit'},
{'createdAt': "2021-01-09T09:12:25.418+00:00", "name": '3 sit'},
{'createdAt': "2021-01-02T08:52:55.418+00:00", "name": '1 dolor'},
{'createdAt': "2021-01-02T08:52:55.418+00:00", "name": '2 dolor'},
{'createdAt': "2021-12-15T09:12:25.418+00:00", "name": '1 ipsum'},
{'createdAt': "2021-12-11T08:52:55.418+00:00", "name": '1 lorem'},
];
console.log('sorted-grouped: ', sortAndGroup(unsortedRawDataArray));
console.log('original-array: ', unsortedRawDataArray);
Explanation
Description of the steps are added to the above code snippet as inline comments.
EDIT
when there is data that has the same date/day the order returns to 1 again,
The data in the array has been updated to have multiple data with same date & the idGroup
is shown to not reset.
besides is there a way to reverse the number without changing the index, for example from 1-3 to 3-1.
This has been done in the updated snippet. After the .flat()
we add another .sort()
which considers not just the date, but also the idGroup
in order to make the numbers go from 3-1 (reverse).
EDIT 2
why after calling the sortAndGroup() function the data from unsortedRawDataArray also changes
This has been fixed. The incoming arr
(array) was directly mutated via .sort
, and the latest version of the answer copies the arr
array.