2

I am trying to sort an array of strings. However some are numbers, some numbers with letters appended, some are letters with numbers appended, and some are purely text. For example:

array = ["100", "2A", "25", "Blue", "1", "X2", "X1", "Yellow", "2"]

I would like the sort the list so it displays the numbers and number-strings in together (1, 2, 2A), then the string-numbers (X1, X2), then finally the strings at the end (Blue, Yellow).

I have tried using array.sort() but this has not worked. What I would like to get returned would be:

["1","2","2A","25","100","X1","X2","Blue","Yellow"]

But instead this would sort lexicographically:

["1","100","2","25,"2A","Blue","X1","X2","Yellow"]

I have also tried splitting into integers and strings, sorting then combining after. But this does not take into account the numbers-string and string-number elements.

Is there any way to make this work?

Geranium42
  • 21
  • 1
  • Well the basic thing is to come up with a comparator function that implements your ordering rules. It should take two parameters (two elements of the array) and return a negative number when the first parameter should go before the second, a positive number when the second one should go first, and 0 if the two parameters have the same ranking. – Pointy Mar 22 '23 at 14:23
  • 2
    You would get a pretty accurate result using `.sort((a,b) => a.localeCompare(b))` – somethinghere Mar 22 '23 at 14:23
  • You'll need to provide a specific condition for 'numbers with letters appended' – pilchard Mar 22 '23 at 14:26
  • Also note that your ordering rules are fairly complicated. When the sort compares `"2"` and `"Yellow"` it's got to figure out that the first one is a number and the second one isn't. For `"X2"` it's got to find the digits embedded in the string. If you have `"AA22B"` and `"b10a"`, well, you have to figure that out too. – Pointy Mar 22 '23 at 14:27

1 Answers1

4

You could move strings with no digits to end and sort the rest by string with options.

const
    noDigits = /^\D+$/g,
    array = ["100", "2A", "25", "Blue", "1", "X2", "X1", "Yellow", "2"]

array.sort((a, b) =>
    noDigits.test(a) - noDigits.test(b) ||
    a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })
);

console.log(...array);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392