2

I have tried variations of two similar questions here:

Sort mixed alpha/numeric array

and here:

Sort mixed alpha/numeric Array in javascript

But can't get the sort algorithm correct.

For example this solution:

const sortAlphaNum = (a, b) => a.localeCompare(b, 'en', { numeric: true })`

Gives it in the format of ["A1", "A2", "A3"...] whereas I want it in the format of ["A1", "B1", "C1"...].

The array ranges from A1 to M30 if that helps so only one letter but two numbers.

Martin Dawson
  • 7,455
  • 6
  • 49
  • 92

3 Answers3

1

Some like this could help

const sortAlphaNum = (a, b) => parseInt(a.replaceAll(/[A-Z]+/ig, '')) - parseInt(b.replaceAll(/[A-Z]+/ig, '')) || a.localeCompare(b);

What it is doing is removing any letter from the value and comparing just the numbers, if the numbers are the same then sort using localeCompare

Martin Dawson
  • 7,455
  • 6
  • 49
  • 92
Aguardientico
  • 7,641
  • 1
  • 33
  • 33
1

You may split into aplpha- and numeric- parts and sort accordingly:

const src = ['C2', 'A1', 'B2', 'A2', 'B1', 'C1'],
      splitAlphaNum = s => s.match(/([A-Z])(\d+)/).slice(1)

      result = src.sort((a,b) => {
        const [a1, n1] = splitAlphaNum(a),
              [a2, n2] = splitAlphaNum(b)
        return n1-n2 || a1.localeCompare(a2)
      })
      
console.log(result)
Yevhen Horbunkov
  • 14,965
  • 3
  • 20
  • 42
1

For the specific range of input you have, you could map the values from A9 to 99A format, sort alphabetically and then map them back. This has as advantage that there is no mapping happening during the sort, which is the most costly step:

let data = ["M12", "K2", "E2", "A3", "A22"];

let result = data.map(s => s.slice(1).padStart(2, "0") + s[0])
                 .sort()
                 .map(s => s[2] + parseInt(s));
                 
console.log(result);
trincot
  • 317,000
  • 35
  • 244
  • 286