5

Firstly I could not find a question addressing the whole issue.

I used to compare arrays like this:

array.sort((a, b) => {
    return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'})
})

But I realized it does not work on an array like ['a', 'A', 'B', -1.50', '0', '1.50', '-2', '2'].

The expected output would be: ['-2', '-1.50', '0', '1.50', '2', 'A', 'a', 'B'].

I have some dirty ideas to achieve it. But maybe there is a clean and easy way.

Ali Ankarali
  • 2,761
  • 3
  • 18
  • 30

3 Answers3

7

You could prepend the comparison by taking the delta of the wanted properties. This saves the order for numerical values.

console.log(
    ['a', 'A', 'B', '-1.50', '0', '1.50', '-2', '2', 'D']
        .sort((a, b) => a - b || a.localeCompare(b, undefined, {sensitivity: 'base'}))
);

numeric: true option can be omitted for there won't be two numbers to compare at the left hand side of the expression.

Ali Ankarali
  • 2,761
  • 3
  • 18
  • 30
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • I guess in this case we already look whether it is number or not, so it would be better if we omit `numeric: true` option for performance. – Ali Ankarali May 09 '18 at 07:57
2

You should use isNaN method in order to check if you compare numerical strings. If yes, localeCompare is not recommended , you need to use Number(a) - Number(b)

array = ['a', 'A', 'B','-1.50', '0', '1.50', '-2', '2']
array.sort((a, b) => {
  return !isNaN(a) && !isNaN(b) ? Number(a)-Number(b) : a.localeCompare(b, undefined, { sensitivity: 'base'});
})
    
console.log(array);

Since in Javascript the - operator is defined only for numeric subtraction, the operands will be coerced to Number. So you could simply use:

array.sort((a, b) => {
  return a - b || a.localeCompare(b, undefined, { sensitivity: 'base'});
})
Mihai Alexandru-Ionut
  • 47,092
  • 13
  • 101
  • 128
2
const customSort = (array) => {
    return array.sort((a, b) => {

        let r = /^-?\d+(?:\.\d+)?$/;

        if (r.test(a) && r.test(b))
        {
            return a - b;
        }

        return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'})
    })
}

console.log(customSort(['a', 'A', 'B', '-1.50', '0', '1.50', '-2', '2']));
// => [ '-2', '-1.50', '0', '1.50', '2', 'a', 'A', 'B' ]
bluelovers
  • 1,035
  • 2
  • 10
  • 22