NeedsHelp
NeedsHelp

Reputation: 437

Is it possible to sort an array of objects in this specific way using sort()?

Sorry for not putting the specific sort in the title but I couldn't word it properly.

I'm sorting a list of file objects that have details such as name, date uploaded and category and I need to sort it in such a way that the last uploaded file is push to the top and the rest of them aren't sorted.

So for example, if I had the list sorted from oldest to newest in descending order I still want the newest one at the top.

The lists are already sorted in terms of category, date, etc. when returned from the database so I just need to further sort it after.

It has to be done in a function that gets passed to a sort().

Upvotes: 1

Views: 65

Answers (3)

Nina Scholz
Nina Scholz

Reputation: 386766

Array#sort is not necessarily stable, as long as you sort just by one property as in the first result.

You need another value for moving equal (resulting with 0) items to the right place, here with additional value of id, which are in creation order.

var data = [{ id: 0, date: '2017-01-01' }, { id: 2, date: '2017-01-01' }, { id: 5, date: '2017-01-02' }, { id: 6, date: '2017-01-05' }, { id: 9, date: '2017-01-06' }, { id: 19, date: '2017-01-11' }, { id: 24, date: '2017-02-01' }, { id: 67, date: '2017-02-01' }, { id: 80, date: '2017-02-11' }, { id: 90, date: '2017-02-21' }, { id: 101, date: '2017-02-23' }, { id: 149, date: '2017-02-28' }, { id: 163, date: '2017-03-01' }, { id: 190, date: '2017-03-02' }, { id: 321, date: '2017-03-05' }, { id: 444, date: '2017-03-17' }],
    lastDate = data[data.length - 1].date;

data.sort(function (a, b) {
    return (b.date === lastDate) - (a.date === lastDate);
});
console.log(data);

data.sort(function (a, b) {
    return (b.date === lastDate) - (a.date === lastDate) || a.id - b.id;
});
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Another solution would be, to use Array#pop for the last item and Array#unshift for inserting at top place of the array.

var data = [{ id: 0, date: '2017-01-01' }, { id: 2, date: '2017-01-01' }, { id: 5, date: '2017-01-02' }, { id: 6, date: '2017-01-05' }, { id: 9, date: '2017-01-06' }, { id: 19, date: '2017-01-11' }, { id: 24, date: '2017-02-01' }, { id: 67, date: '2017-02-01' }, { id: 80, date: '2017-02-11' }, { id: 90, date: '2017-02-21' }, { id: 101, date: '2017-02-23' }, { id: 149, date: '2017-02-28' }, { id: 163, date: '2017-03-01' }, { id: 190, date: '2017-03-02' }, { id: 321, date: '2017-03-05' }, { id: 444, date: '2017-03-17' }];

data.unshift(data.pop());
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

AP.
AP.

Reputation: 8931

You can achieve this by simply compound your sorting algorithm:

sortingLabels = ["date uploaded", "category", "date"]
myArray.sort((a,b) => {
  for (l of sortingLabels) {
    const comparison = compare(a,b,l)
    if (comparison == 0) {continue}
    return comparison
  }
})

Now all you have to do is implement a compare(a,b,label) function that returns -1,1, or 0 based on the label.

Note: The for loop for-of works in ES2015+, which is most modern browsers and Node.js. However, if you need to support significantly older browsers, you might want to consider using a general for-loop

Upvotes: 0

Johan Willfred
Johan Willfred

Reputation: 851

There are a lot of solutions for this. As simplest solution you can use something like https://lodash.com/docs/4.17.4#orderBy

Upvotes: 1

Related Questions