Search code examples
javascriptsortingalphanumericnatural-sort

Alphanumerical / Natural Sort an Array with leading zeroes in Javascript


I need to sort through an array of strings that contain letters / numbers / and leading zeros. If null it must go to the top of the list and appear as an empty string. I've looked and researched many different ways but nothing that sorts the way I'm expecting it to.

Initial Array:

input = [
    { value: null },
    { value: '' },
    { value: '-' },
    { value: '0' },
    { value: 'A1' },
    { value: '0001' },
    { value: '01' },
    { value: '1' },
    { value: '01.008A' },
    { value: '01.008' },
    { value: '02' },
    { value: 'A' },
    { value: '10' },
    { value: '100A1' },
    { value: '10-1' },
    { value: '100' },
    { value: '001' },
    { value: '2' },
  ]

Expected Output:

  1. " "
  2. " "
  3. "-"
  4. "0"
  5. "0001"
  6. "001"
  7. "01"
  8. "01.008"
  9. "01.008A"
  10. "1"
  11. "02"
  12. "2"
  13. "10"
  14. "10-1"
  15. "100"
  16. "100A1"
  17. "A"
  18. "A1"

EDIT: (My Original Code)

function sortAlphanumeric<T>(this: Array<T>, property: string): Array<T> {
  var collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });

  function dynamicSort(property) {
    var sortOrder = 1;

    if (property[0] === "-") {
      sortOrder = -1;
      property = property.substr(1);
    }

    return function (a, b) {
      if (sortOrder == -1) {
        return b[property].localeCompare(a[property]);
      } else {
        return a[property].localeCompare(b[property]);
      }
    }
  }
  return this.sort(dynamicSort(property)).sort((a, b) => {
    var nullToEmptyString = '';

    if (a[property] === null) {
      a[property] = nullToEmptyString;
    }

    if (b[property] === null) {
      b[property] = nullToEmptyString;
    }
    return collator.compare(a[property], b[property]);
  });
}

Solution

  • This should do it:

    input.sort(({value:a}, {value:b}) => {
      const ai = parseInt(a, 10), bi = parseInt(b, 10);
      return (b == null) - (a == null)
        || (ai - bi)
        || (a > b) - (b > a);
    }).map(x => x.value || "")