Search code examples
javascriptarrayssortingalphanumeric

Sort alphanumeric strings - Letters first


var List = ["F", "60", "59", "6", "7", "7'", "60'", "60a", "c1", "A", "5", "a1", "6.2", "A'", "B", "A1"];

var sortedListe = List.sort(function (a, b) {
  var collator = new Intl.Collator('en', { numeric: true, sensitivity: "base" });
  return collator.compare(a, b);
});

console.log(sortedListe);

What I get: ["5", "6", "6.2", "7", "7'", "59", "60", "60'", "60a", "A", "A'", "a1", "A1", "B", "c1", "F"]

https://jsfiddle.net/5coraw0z/

PRO: 6.2 comes before 7; 7' is also in the right place; c1 is between B and F. CONTRA: Strings beginning with a letter are at the end of the list.

My expected result: ["A", "A'", "a1", "A1", "B", "c1", "F", "5", "6", "6.2", "7", "7'", "59", "60", "60'", "60a"]


Solution

  • If you need non-standard sorting rules, it's often easier to sort each part of the array separately rather than inventing a convoluted sorting callback:

    function partition(ary, fn) {
        let res = [[], []]
        for (let x of ary)
            res[fn(x) ? 1 : 0].push(x)
        return res
    }
    
    let List = ["F", "60", "59", "6", "7", "7'", "60'", "60a", "c1", "A", "5", "a1", "6.2", "A'", "B", "A1"];
    
    let collator = new Intl.Collator('en', { numeric: true, sensitivity: "base" });
    
    let sortedListe = [].concat(
      ...partition(List, x => !isNaN(x[0]))
        .map(a => a.sort(collator.compare)))
    
    console.log(...sortedListe);