I have data that is coming from the server like this
let value = [
{
'commongId': 1,
'principal': true,
'creationDate': '2019-11-03:40:00'
},
{
'commongId': 2,
'principal': false,
'creationDate': '2017-10-25T01:35:00'
},
{
'commongId': 2,
'principal': true,
'creationDate': '2019-05-25T08:00:00'
},
{
'commongId': 1,
'principal': false,
'creationDate': '2018-11-25T09:40:00'
},
{
'commongId': 1,
'principal': false,
'creationDate': '2017-11-25T09:40:00'
},
{
'commongId': 2,
'principal': false,
'creationDate': '2018-05-25T08:00:00'
},
]
I want to transform it in a way that the courses are grouped by commonId, and that the principal course of each 'id' should appear first, and the rest of the courses belonging to the same commonId come after that principal course sorted by the creation date (asc).
So basically the output should be
let value = [
{
commongId: 1,
principal: true,
creationDate: '2019-11-03:40:00'
},
{
commongId: 1,
principal: false,
creationDate: '2017-11-25T09:40:00'
},
{
commongId: 1,
principal: false,
creationDate: '2018-11-25T09:40:00'
},
{
commongId: 2,
principal: true,
creationDate: '2019-05-25T08:00:00'
},
{
commongId: 2,
principal: false,
creationDate: '2017-10-25T01:35:00'
},
{
commongId: 2,
principal: false,
creationDate: '2018-05-25T08:00:00'
}
];
I have a working solution, which in my opinion looks horrible and too complicated.
// function to group the the courses by commonId
const groupBy = (data, keyFn) =>
data.reduce((agg, item) => {
const group = keyFn(item);
agg[group] = [...(agg[group] || []), item];
return agg;
}, {});
let transformedValue = groupBy(courses, item => item.commonId);
//removing the keys from the array of objects
transformedValue = Object.keys(transformedValue).map(k => transformedValue[k]);
// sorting each inner array by creationDate
transformedValue = transformedValue.map(el => {
let modified = el.sort((a, b) =>
moment(a.creationDate).diff(moment(b.creationDate))
);
// pushing the principal object of each array to the top
const foundIndex = modified.findIndex(element => element.principal);
if (foundIndex > -1) {
const foundElement = modified.find(element => element.principal);
modified.splice(foundIndex, 1);
modified.unshift(foundElement);
}
return modified;
});
// flattening the array to one level
transformedValue = transformedValue.flat();
// using the transformed value in the subscription
of(transformedValue).subscribe(p => {
this.dataToShow = p;
});