How to sort a numeric array?
How to sort an array of objects by several fields?

  • 3
    He asked himself - he answered right away. Often so;) And why, if not a secret? Purely for educational purposes? - AseN pm
  • one
    @ 0xFFh, met another garden from conditional operators and decided to write :) - Qwertiy
  • @PavelMayorov, and what sort of label did not please? - Qwertiy pm

1 answer 1

Standard sorting

The sort function by default leads the array elements to strings, and then sorts.

 [1,-8,90,32,0,0,5,92,900].sort() // [-8, 0, 0, 1, 32, 5, 90, 900, 92] 

If the array consists of numbers, then this behavior is undesirable.

Using Comparator

The sort function can take an argument — a comparator.

A comparator is a function that takes 2 arguments and returns a negative number if the first is less, positive if the second is less and 0 if they are equal.

For numbers, subtraction as a comparator is quite common:

 [1,-8,90,32,0,0,5,92,900].sort(function(a, b) { return ab; }) // [-8, 0, 0, 1, 5, 32, 90, 92, 900] 

In general, one should be wary of this construction due to possible overflow, but in most cases it works.

Comparator based on comparison

It may be recalled that in many languages ​​true is reduced to 1, and false to 0.

Take advantage of this opportunity. Only one of the conditions a<b and b<a true, so the difference (b<a) - (a<b) remarkably suitable for the role of the comparator:

 [1,-8,90,32,0,0,5,92,900].sort(function(a, b) { return (b<a) - (a<b); }) // [-8, 0, 0, 1, 5, 32, 90, 92, 900] 

What are the advantages? In addition to the impossibility of overflow, such a comparison can be used not only with numbers. For example, we cannot subtract lines, but we can compare.

To sort in descending order you just need to swap the comparisons:

 [1,-8,90,32,0,0,5,92,900].sort(function(a, b) { return (a<b) - (b<a); }) // [900, 92, 90, 32, 5, 1, 0, 0, -8] 

Sort by multiple fields

When comparing over several fields, it is required that the next field be compared only when the previous ones are equal. This means that the part of the comparator that performs the comparison of those fields in the calculation gives 0.

Thus, the operator || that returns the first true (in our case, non-zero) value, or the most recent (in our case, 0) if all are false. In this way, you can combine any number of fields.

Sort the array by name and id:

 [{name:"John", id:7}, {name:"John",id:4}, {name:"Adam",id:3}, {name:"Adam",id:30}, {name:"Rose",id:1}].sort(function(a, b) { return (b.name<a.name) - (a.name<b.name) || (b.id<a.id) - (a.id<b.id); }) // [{"name":"Adam","id":3},{"name":"Adam","id":30},{"name":"John","id":4},{"name":"John","id":7},{"name":"Rose","id":1}] 

    Protected by member Qwertiy Mar 12 '18 at 17:41 .

    Thank you for your interest in this issue. Since he collected a large number of low-quality and spam responses, which had to be deleted, now it’s necessary to have 10 reputation points on the site (the bonus for account association is not counted ).

    Maybe you want to answer one of the unanswered questions ?