'sort function unexpected behaviour

i am trying to understand array sorting method , the problem i am currently facing is when i am declaring some variables inside compare function its not sorting the same as it is doing without those variables although those variables are not used anywhere

can anyone explain what is actually happening here

also i find out that sort functions behave different in firefox and chrome page_link i am testing this in firefox dev edition

browser_screenshot

let list1 = ["a","b","c","d","e","f","g","h","i"]

list1.sort((a,b)=>{
    let pat = ["d","a"]
    return b - a
})
console.log(list1) // Array(9) [ "a", "b", "c", "d", "e", "f", "g", "h", "i" ]

let list2 = ["a","b","c","d","e","f","g","h","i"]

list2.sort((a,b)=>{
    // let pat = ["d","a"]
    return b - a
})
console.log(list2) // Array(9) [ "i", "h", "g", "f", "e", "d", "c", "b", "a" ]


Solution 1:[1]

If you do "a" - "b" it evaluates to NaN which is incorrect as that's not what you intended and also inconsistent (varies browser to browser).

Either don't pass a callback to sort in which case it does the following:

The sort() method sorts the elements of an array in place and returns the sorted array. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.

Or you can use String.prototype.localeCompare

let list = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];

console.log([...list].sort());

console.log([...list].sort((a, b) => a.localeCompare(b)));

If you want to prepend some values to the sorted array you'll have to do it separately you can't do it using sort.

let list = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];

let pat = ["x", "y"];

let sortedList = [...list].sort();

let patAppendedSortedList = [...pat, ...sortedList];

console.log(patAppendedSortedList);

And if you want to sort both the list and pat but you want to keep all pat elements before all list elements then consider the snippet below.

let list = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];

let pat = ["z", "x", "y"];

let patSet = new Set(pat);

let sortedList = [...pat, ...list].sort((a, b) => {
  // If a has higher priority put it before b
  if (patSet.has(a) && !patSet.has(b)) {
    return -1;
  }
  // If b has higher priority put it before a
  if (patSet.has(b) && !patSet.has(a)) {
    return 1;
  }

  // Otherwise both a and b have same priority
  // Sort them according to their value
  return a.localeCompare(b);
});

console.log(sortedList);

Solution 2:[2]

If you subtract a string from another string, it will attempt to convert the strings to numbers.

All of your strings will convert to NaN.

NaN-NaN is also NaN.

So it doesn't matter which two values from your array you are comparing, your comparison function will always return NaN.

(Note that a comparison function is supposed to return a number that is 0, greater than 0 or less than 0 and be consistent for any given pair of values. The one you are using is just broken for the data you are using).

The order the letters get sorted into therefore depends on the order in which they are compared to each other (because your comparison function is broken).

That order is determined by the sort algorithm that the JS engine uses. This is an implementation detail that the specification doesn't mandate.

One browser might use a quick sort while another might use a bubble sort. Hence you get different results.


Write a comparison function which isn't nonsense to get consistent results.

The default comparison function is find for lexical sorting under most circumstances.

Solution 3:[3]

Now i understood your goal. But you cant archive this with your way. You cant make some prepends of values in the JS sort function. You have to make it in two steps. 1.) sort 2.) prepend your pat values to the sorted array.

const list = ["a","b","c","d","e","f","g","h","i"];

const pat = ["d","a"]; 
const sorted = [...pat, ...list.sort()];

console.log(sorted)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Quentin
Solution 3