7

I have array containing random numbers. When I trying to sort this array via .sort() method, the result is different if array contains duplicate numbers. The code below works differently in Chrome and Firefox:

[1,2,3,4,5,6,7,8,9,2,15,3,4,5,1,2,3,4,0,2,3].sort(function(a, b) {
  console.log("a=", a, "b=", b)
})

Plunker: http://plnkr.co/edit/Ocm1ZSXgkoCM7FQeH0v5

Does it bug ? How to fix this behavior to have same result in Chrome and FF ?

5
  • 4
    Your sort function is wrong. Since it returns undefined for every single comparison, it's expected that sorting won't work. Commented Nov 9, 2016 at 21:51
  • @vlaz I've updated the plunk Commented Nov 9, 2016 at 21:54
  • @vlaz please look my latest comments under answer stackoverflow.com/a/40516655/5397119 Commented Nov 9, 2016 at 22:06
  • 1
    I have. You cannot do what you're trying to do with this function. See here for why that might be a problem. Commented Nov 9, 2016 at 22:08
  • 1
    @vlaz pls check if my answer is doing what he is trying to do Commented Nov 9, 2016 at 22:54

2 Answers 2

7

It works with a proper return value.

var array = [1,2,3,4,5,6,7,8,9,2,15,3,4,5,1,2,3,4,0,2,3];

array.sort(function(a, b) {
    return a - b;
});
console.log(array);

array.sort(function(a, b) {
    return (a & 1) - (b & 1) || a - b;
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

16 Comments

this code still returns different results in console.log() for Chrome and FF
I really doubt it
@SergioIvanuzzo the result is the same. Ignore the other output - the browsers simply use different sorting algorithms.
@SergioIvanuzzo so what do you expect to happen? Two different sorting algorithms are deployed. Your output will be sorted as much as you've allowed it to be sorted. If you don't consider 1 and 3 to be different then they might or might not get shifted along. If you want the sorting to be stable, use a stable sorting function. Right now you are not allowing JS to sort it correctly because different inputs produce a different output.
@JohnnyAW again, Bergi has a brilliant writeup on sorting here. Also, yeah, Plunkr is bad - you have to open the console to see the output. It's annoying. It's as if JSBin and StackOverflow (with snippets) are the only websites that realised how to do it properly
|
4

Since sort() is not necessarily stable, you need to save the position of an element before sorting and use it as compare parameter if the value is equal, if you want to keep the position in the result array . But the problem in your case is, you have multiple values and can't just look up the position in the starting-array. You need to wrap your values in objects:

var values= [1,2,3,4,5,6,7,8,9,2,15,3,4,5,1,2,3,4,0,2,3];
var wrappedValues = [];
//first create wrapped values
for(var i = 0;i < values.length;i++){
    wrappedValues.push({value : values[i], index : i});
}
//now sort wrapped values
wrappedValues.sort(function(a, b) {
    var result = a.value % 2 - b.value % 2;
    if(result == 0){
        return a.index - b.index;
    }
    return result;
});
//now unwrappe the values:
var unwrappedValues = [];
wrappedValues.forEach(function(entry) {
    unwrappedValues.push(entry.value);
});
console.log(unwrappedValues );

btw. part of your Problem is in the compare function from the answer you provided:

return a % 2 - b % 2 || a - b;

this function is sorting ascending in || a - b - part

4 Comments

If I'm not mistaken, that's the decorate-sort-undecorate pattern, though it's usually done as .map(/* decorate */).sort().map(/* undecorate */) which avoids declaring the intermediate temporary values.
@vlaz but .map() creates a new Array, so how would this avoid declaring the intermediate temporary values? o.O
Well, you don't have to declare them. Obviously they still exist but you don't need to care about that in your code. All you need here is input -> output and something called wrappedValues is merely noise. Similarly, the name unwrappedValues is also just noise - do you really, honestly care that the values were once wrapped in something when they are presented as plain values again?
@vlaz oh wait, you said "declared".. nvm. I misread again :D Yeah, you're right, that would be much shorter. But I will still leave the code this way so the OP can easier understand 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.