My purpose is to get from this:
const grouped = [
{
"2022/11": [
{
"2022/11/30": [
{
"breaking-change": [
{
date: "2022-11-30T07:33:07.992955008Z",
reponame: "test-repo",
status: "breaking-change",
},
],
},
],
},
{
"2022/11/29": [
{
compatible: [
{
date: "2022-11-29T14:58:44 01:00",
reponame: "test-repo",
status: "compatible",
},
],
},
],
},
],
},
{
"2022/10": [
{
"2022/10/17": [
{
compatible: [
{
date: "2022-10-17T14:58:44 01:00",
reponame: "test-repo",
status: "compatible",
},
],
},
],
},
],
},
];
This:
[
{
"2022/10": [
{
"2022/10/17": [
{
compatible: [
{
date: "2022-10-17T14:58:44 01:00",
reponame: "test-repo",
status: "compatible",
},
],
},
],
},
],
},
{
"2022/11": [
{
"2022/11/29": [
{
compatible: [
{
date: "2022-12-17T14:58:44 01:00",
reponame: "test-repo",
status: "compatible",
},
],
},
],
},
{
"2022/11/30": [
{
"breaking-change": [
{
date: "2022-11-30T07:33:07.992955008Z",
reponame: "test-repo",
status: "breaking-change",
},
],
},
],
},
],
},
];
So:
"month-objects" ( the example would be the one in the parent array with
2022/11
as a key ) needs to be sorted by key(date/month) in an ascending way;and also "days-objects" (the example would be the one in the first-level-children array with
2022/11/30
as a key ) needs to be sorted by key(date/month) in an ascending way;
That's what I tried:
const sortedGrouped = grouped.sort(function (a, b) {
return (
new Date(Object.keys(a)[0]).getTime() -
new Date(Object.keys(b)[0]).getTime()
);
});
That way I can only sort parents.
Tried to sort first-level children, but getting an Invalid left-hand side in assignment expression
issue:
grouped.forEach((obj) => {
Object.values(obj) = Object.values(obj).sort(function (a, b) {
return (
new Date(Object.keys(a)[0]).getTime() -
new Date(Object.keys(b)[0]).getTime()
);
});
});
This one doesn't work for me either:
const sortByDate = arr => {
const sorter = (a, b) => {
return new Date(Object.keys(a)[0]).getTime() - new Date(Object.keys(b)[0]).getTime();
};
arr.forEach((i)=>Object.values(i).sort(sorter))
return arr;
};
CodePudding user response:
The most generic solution has to based on a recursive approach.
Thus one does
- either
- try to sort an array by retrieving a
Date
related value from each of its items, - and keep the recursion going for each item of the just sorted array,
- try to sort an array by retrieving a
- or
- keep the recursion going for each value of an
object
type item.
- keep the recursion going for each value of an
Which directly leads to two other tasks
a function which from each passed object tries to parse a valid
Date
instance fromand a helper function which checks whether a passed value is a valid date.
The first mentioned of the latter two functions does so by either assuming an existing date
property of the passed value or by going with the first validly parsed date from one of the passed value's keys.
function isValidDate(date) {
const time = date?.getTime?.() ?? Number.NaN;
return (
'number' === typeof time
&& !Number.isNaN(time)
);
}
function parseDateFromItem({ date: dateTime = null, ...itemData }) {
let date;
// parse into a `Date` instance ...
if (dateTime !== null) {
// ... either directly from an available `date` key ...
date = new Date(dateTime);
} else {
// ... or from the first validly parsable property name.
Object
.keys(itemData)
.some(key => {
date = new Date(key);
return isValidDate(date);
});
}
return isValidDate(date) && date || null;
}
function recursivelySortItemsAscendingByParsableDate(data) {
if (Array.isArray(data)) {
data
.sort((a, b) =>
(parseDateFromItem(a) ?? 0) - (parseDateFromItem(b) ?? 0)
);
data
.forEach(recursivelySortItemsAscendingByParsableDate);
} else if (data && 'object' === typeof data) {
Object
.values(data)
.forEach(recursivelySortItemsAscendingByParsableDate);
}
}
const sampleData = [{
"2022/11": [{
"2022/11/30": [{
"breaking-change": [{
date: "2022-11-30T07:33:07.992955008Z",
reponame: "test-repo",
status: "breaking-change",
}],
}],
}, {
"2022/11/29": [{
compatible: [{
date: "2022-11-29T14:58:44 01:00",
reponame: "test-repo",
status: "compatible",
}],
}],
}],
}, {
"2022/10": [{
"2022/10/17": [{
compatible: [{
date: "2022-10-17T14:58:44 01:00",
reponame: "test-repo",
status: "compatible",
}],
}],
}],
}];
recursivelySortItemsAscendingByParsableDate(sampleData);
console.log({ sampleData });
const moreSampleData = [{
"2022/12": [{
"2022/12/17": [{
compatible: [{
date: "2022-12-17T14:58:44 01:00",
reponame: "test-repo",
status: "compatible"
}]
}]
}]
}, {
"2021/11": [{
"2021/11/30": [{
compatible: [{
date: "2021-11-30T07:33:07.992956372Z",
reponame: "test-repo",
status: "compatible"
}]
}]
}]
}, {
"2022/11": [{
"2022/11/30": [{
compatible: [{
date: "2022-11-30T07:33:07.992956372Z",
reponame: "test-repo",
status: "compatible"
}, {
date: "2022-11-25T07:33:07.992955008Z",
reponame: "test-repo",
status: "compatible"
}]
}, {
"breaking-change": [{
date: "2022-11-30T07:33:07.992955008Z",
reponame: "test-repo",
status: "breaking-change"
}]
}, {
"need-an-update": [{
date: "2022-11-30T07:33:07.992955008Z",
reponame: "test-repo",
status: "need-an-update"
}]
}]
}, {
"2022/11/29": [{
compatible: [{
date: "2022-12-17T14:58:44 01:00",
reponame: "test-repo",
status: "compatible"
}]
}]
}]
}];
recursivelySortItemsAscendingByParsableDate(moreSampleData);
console.log({ moreSampleData });
.as-console-wrapper { min-height: 100%!important; top: 0; }