Updated example, as it didn't match to the object structure which was given in the post
There is an array, which has multiple objects like this:
{
text: text,
elements: [
{
id: id,
page: pageNumber
}
]
}
Now I need to sort the content in two ways:
text
-fieldI would do like this:
array.sort(function(a,b) {
if (a.text < b.text) return -1;
if (a.text > b.text) return 1;
return 0;
});
elements
-array should also be sorted by the page
-field.I don't know how to sort an array, which is nested in the objects... Unfortunately it gets more difficult as the elements are strings, but represent some page numbers. So how can I sort these data in a correct way, as elements could look like 123
or 23-34
? And in the case 123-125
, 23-34
, the last element should be the first.
Example
[
{
text: 'Some text',
elements: [
{ id: 1, pages: '45-67' },
{ id: 2, pages: '12-34' }
]
},
{
text: 'Another text',
elements: [
{ id: 3, pages: '12-34' }
]
}
]
Should be sorted to:
[
{
text: 'Another text',
elements: [
{ id: 3, pages: '12-34' }
]
},
{
text: 'Some text',
elements: [
{ id: 2, pages: '12-34' },
{ id: 1, pages: '45-67' }
]
},
]
So the object order has changed, as A is before S and the order of the page elements in the (now) second object are ordered the other way round.
For the first part, you could use the power of String#localeCompare
. And use for the page array another sort function with splitting the string.
var array = [{ id: 1, text: 'Some text', elements: [{ id: 1, pages: '45-67' }, { id: 2, pages: '12-34' }, { id: 4, pages: '12-5' }, { id: 5, pages: '12' }] }, { id: 3, text: 'Another text', elements: [{ id: 3, pages: '12-34' }] }];
array.sort(function (a, b) {
return a.text.localeCompare(b.text);
});
array.forEach(function (el) {
el.elements.sort(function (a, b) {
var aa = a.pages.split('-'),
bb = b.pages.split('-');
return aa[0] - bb[0] || (aa[1] || 0) - (bb[1] || 0);
});
});
console.log(array);
The problem is not a difficult one, as the author has already broken down the problem into smaller chunks. For instance - you mentioned sort the text first and then the nested property (pages), which you are having trouble with.
Your use case is easier as we know you are dealing with pages, so the page numbers will be consistent. E.g. It is unlikely to have entry like '10-20' and '10-15', well if they do then my code below will have to expand a bit to handle this sort of situation.
Otherwise what I have done below is to split the string entry using the -
character as delimeter to get a fromPage
and toPage
parameter. Then using the fromPage we do the usual compare in the sort
function to determine who is smaller.
Once that is sorted, then I sort the outer items which you already got a solution for it.
Solution:
// Sort the nested properties first - in this instance it will be page
example.forEach(item => {
item.pages.sort(function (a, b) {
aFromPage = a.split('-')[0];
bFromPage = b.split('-')[0];
// Assuming from page number is unique, if it is not unique then the ToPage number can be
// used for comparison also.
return (aFromPage < bFromPage) ? -1 : 1;
})
});
// Handle the outer item
example.sort(function(a,b) {
if (a.text < b.text) return -1;
if (a.text > b.text) return 1;
return 0;
});
console.log(JSON.stringify(example));
Output:
[
{
"id" : 3,
"text" : "Another text",
"pages":
[
"1-11",
"12-34",
"35-100"
]
},
{
"id" : 1,
"text" : "Some text",
"pages":
[
"12-34",
"35-44",
"45-67",
"68-100"
]
}
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With