4

Now I know this will be a stupid question to many, but I cannot understand this logic. So, here is the problem in short:

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a-b});

Now suppose, values 40 and 100 are compared, so the compare function returns a negative value, i.e -60. So, 40 is placed before 100. Understood.

Now, I do this:

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return b-a});

Again, if 100 and 40 are compared, the compare function returns a positive value, i.e 60. Now, shouldn't it place 100 after 40 because of that positive returned value? But it doesn't, and I am not getting that.

I just want to know what is happening here.

2
  • To compare numbers: function(a, b){ if (b > a) return -1; if (b < a) return 1; return 0; }. Commented Dec 4, 2015 at 16:32
  • Of course it will be simple reverse. Commented Dec 4, 2015 at 16:38

5 Answers 5

3

Your compare functions are exactly correct - you are using subtraction, which is very fast compared to branching and is in fact what a typical processor does when comparing two integer values. Essentially:

  • If your compare function returns 0, it doesn't matter what order the two should be in.
  • If your compare function returns less than 0 (it doesn't matter how far), the first argument should go before the second argument.
  • If your compare function returns greater than 0 (again, it doesn't matter how far), the second argument should go before the first argument.

This last bit was where you got confused in your logic - in your head, you flipped both the order of the values and changed "before" to "after", which brings the statement right back to the first one again. :) Remember - the names of the parameters or whatever happens to them in the function does not matter - it is simply the order they come in the function arguments and the corresponding result returns.

Sign up to request clarification or add additional context in comments.

2 Comments

I disagree that subtraction is faster than using equality checks. More specifically, what happens when you subtract the maximum int value from any negative int? It'll overflow causing unexpected results - that is why subtraction is avoided in number comparison.
@cricket_007: Well, it is faster - it's just less secure and has a chance to get wrong. However, this is totally fine in JavaScript because all of the numbers are doubles, so any wildly different comparisons will return positive or negative infinity (which still satisfies the spec for the compare function). And even in the integer case, there's probably a way to check the carry bit or to add an extra bit to the subtraction and still be faster than multiple branches.
3

From the Mozilla documentation:

If compareFunction is supplied, the array elements are sorted according to the return value of the compare function. If a and b are two elements being compared, then:

If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first. If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.

If compareFunction(a, b) is greater than 0, sort b to a lower index than a.

compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned then the sort order is undefined.

Imagine that your Array has only 2 items: 100 and 60. What happens is that when 100 is compared with 60 the function returns 40, which is a positive value. When 60 is compared with 100 the function returns -40 which is a negative value... That's how sort knows where to put each element.

Perhaps you are getting confused because you don't understand how sorting algorithms work internally, if that's the case have a look at these 2:

5 Comments

I agree on that, but I don't think that answered my question. How is it possible for the method to put 100 before 40 on a positive return value?
So, the comparison between 60 and 100 is done after the comparison between 100 and 60?
@Siddhantinf "If compareFunction(a, b) is greater than 0, sort b to a lower index than a." So with [40, 100, …], the first parameters passed to the function(a, b){return b-a} are a = 40 and b = 100, which returns 100-40 or 60 which is "greater than 0". Therefore "sort b (100) to a lower index than a (40)".
@Siddhantinf I've updated my answer, please have a look at the latest update.
@Josep, your answer was really informative, thnx for the help
1

Be aware that your comparison function is not guaranteed to be called only once per entry of your array, and it is certainly not done in linear time (O(n)) but depending on the algorithm, it is at best O(n log n).

What I mean is that, 40 will not only be compared to 100, but also to 1 and 5 etc. so you (human) can't really predict at sight that 100 - 40 will sort it in the specific way you expect it to just after the comparison (several comparisons occur per value), because there are several steps that determine the final index of each value.

2 Comments

I completely agree. So, after the function is complete, still 100 is placed before 40, so what is happening, even when each value is compared to the other value?
it will sort it descending instead of ascending
1

According to definition of sort() method is to sort the elements of an array in place and returns the array. The default sort is according to string Unicode code points.

Compare pudocode looks like:

function compare(a, b) {
  if (a is less than b by some ordering criterion) {
     return -1;
  }
  if (a is greater than b by the ordering criterion) {
    return 1;
  }
  // a must be equal to b
  return 0;
}

To compare number:

function compare(a, b) {
   return a - b;
}

Comments

1

Functionally, (ignoring the fact that integer overflow occurs for the maximum values), what happens for ascending order (a-b), is equivalent to the following.

var ascSort = function(a, b) {
    if (a > b) { 
        return 1;
    }  else if (a < b) {
        return -1;
    } else {
        return 0;
    }
}

And descending order, just negate the return values to flip the ordering

var descSort = function(a, b) {
    if (a > b) { 
        return -1;
    }  else if (a < b) {
        return 1;
    } else {
        return 0;
    }
}

And so you can now do

[40, 100, 1, 5, 25, 10].sort(ascSort); // [1, 5, 10, 25, 40, 100]
[40, 100, 1, 5, 25, 10].sort(descSort); // [100, 40, 25, 10, 1] 

3 Comments

as per the information you gave, still 100 > 40. So, it returns a positive value. So, why is 100 placed before 40?
Because b-a = 100 - 40 = 60 > 0, therefore it is a descending sort. I have updated my answer to clarify.
thnx a lot for the help, really appreciate it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.