Reputation: 33
I have two arrays in Javascript coming from Php. I merge these arrays into one array.
All of arrays' elements has created_at
value (Laravel). I want to sort these values by created_at
Problem: Regardless of their date. First array's elements never take place in behind of those of second array
Example: B has latest date. But even so, C (comes from second array) takes place after B.
The problem is although I merged these two arrays into one array. Javascript still thinks "there are two arrays. I should sort first array's elements then those of second array."
What do I do is :
history.push(...response.data[0]); // first array's values
history.push(...response.data[1]); // second array's values
history.sort((a, b) => {
return a.created_at - b.created_at;
});
so, history like
[
// Comes from first array
{
name: 'A',
created_at: '08/09/2021'
},
// Comes from first array
{
name: 'B',
created_at: '15/09/2021'
},
// This third element comes from second array.
{
name: 'C',
created_at: '08/09/2021'
}
]
I expect this result:
new sorted history:
{
name: 'A',
created_at: '08/09/2021'
},
{
name: 'C',
created_at: '08/09/2021'
},
{
name: 'B',
created_at: '15/09/2021'
}
But Javascript initially sorts first array's element. After, sort second array's element then what comes out is:
{
name: 'A',
created_at: '08/09/2021'
},
{
name: 'B',
created_at: '15/09/2021'
},
{
name: 'C',
created_at: '08/09/2021'
},
Upvotes: 3
Views: 187
Reputation: 19070
To sort by date values you can use Date.prototype.getTime():
const arr1 = [{name: 'A', created_at: '08/09/2021'}]
const arr2 = [{name: 'B', created_at: '15/09/2021'}, {name: 'C', created_at: '08/09/2021'}]
const toNumber= d => +d.replace(/\//g, '')
const result = [...arr1, ...arr2].sort((a, b) => toNumber(a.created_at) - toNumber(b.created_at))
console.log(result)
Upvotes: 0
Reputation: 106
You need to send a custom sort function to Array.sort()
const array =
[
{ name: 'A', created_at: '08/09/2021' },
{ name: 'B', created_at: '15/09/2021' },
{ name: 'C', created_at: '08/09/2021' }
];
const ymd = (dmy) => { let a = dmy.split('/'); return a[2] + '/' + a[1] + '/' + a[0] }
const sorted = array.sort((elem1, elem2) => ymd(elem1.created_at) > ymd(elem2.created_at) ? 1 : -1);
console.log(sorted);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Edit:
If you need the sort to be stable (meaning it does not ever arbitrarily swap objects with equivalent comparison values) or by date first and alpha second, then you will need a more complex sort function.
With a little more time and a localeCompare()
suggestion form Felix Kling I wrote an improved sort that is stable and will sort by date first and name second.
const array =
[
{ name: 'A', created_at: '08/09/2021' },
{ name: 'Z', created_at: '15/09/2021' },
{ name: 'D', created_at: '15/09/2021' },
{ name: 'B', created_at: '15/09/2021' },
{ name: 'C', created_at: '08/09/2021', stable: '1'},
{ name: 'S', created_at: '08/09/2020' },
{ name: 'C', created_at: '08/09/2021', stable: '2' },
{ name: 'C', created_at: '08/06/2021' }
];
const ymd = (dmy) => { let a = dmy.split('/'); return a[2] + '/' + a[1] + '/' + a[0] }
const sorted = array.sort((elem1, elem2) =>
(ymd(elem1.created_at) === ymd(elem2.created_at)) ?
elem1.name.localeCompare(elem2.name) :
ymd(elem1.created_at).localeCompare(ymd(elem2.created_at)));
console.log(sorted);
Outputs:
[
{ name: 'S', created_at: '08/09/2020' },
{ name: 'C', created_at: '08/06/2021' },
{ name: 'A', created_at: '08/09/2021' },
{ name: 'C', created_at: '08/09/2021', stable: '1' },
{ name: 'C', created_at: '08/09/2021', stable: '2' },
{ name: 'B', created_at: '15/09/2021' },
{ name: 'D', created_at: '15/09/2021' },
{ name: 'Z', created_at: '15/09/2021' }
]
Upvotes: 1
Reputation: 22524
You can array#concat
both your array and use Schwartzian transform
to sort your array by converting the created_at
to YYYY-MM-DD
format which could be sorted lexicographically.
const arr1 = [{name: 'A', created_at: '08/09/2021'}],
arr2 = [{name: 'B', created_at: '15/09/2021'}, {name: 'C', created_at: '08/09/2021'}],
result = arr1.concat(arr2)
.map(o => [o.created_at.replace(/(..)\/(..)\/(....)/, '$3-$2-$1'), o])
.sort((a,b) => a[0].localeCompare(b[0]))
.map(([,o]) => o);
console.log(result)
Upvotes: 4