0

Hello I'm trying to sort an array.

e.g. input

['/catalog/tag/categories/0', 
'/catalog/tag/categories/0/categories/0', 
'/catalog/tag/categories/0/categories/1', 
'/catalog/tag/categories/1', 
'/catalog/tag/categories/1/categories/0', 
'/catalog/tag/categories/1/categories/1', 
'/catalog/tag/categories/2', 
'/catalog/tag/categories/2/categories/0', 
'/catalog/tag/categories/2/categories/1', 
'/catalog/tag/categories/2/categories/10', 
'/catalog/tag/categories/2/categories/11', 
'/catalog/tag/categories/2/categories/14', 
'/catalog/tag/categories/2/categories/15', 
'/catalog/tag/categories/2/categories/16', 
'/catalog/tag/categories/2/categories/17', 
'/catalog/tag/categories/2/categories/2', 
'/catalog/tag/categories/2/categories/3', 
'/catalog/tag/categories/2/categories/7', 
'/catalog/tag/categories/2/categories/8', 
'/catalog/tag/categories/2/categories/9'];

e. g. output should be like below

['/catalog/tag/categories/0', 
'/catalog/tag/categories/0/categories/0', 
'/catalog/tag/categories/0/categories/1', 
'/catalog/tag/categories/1', 
'/catalog/tag/categories/1/categories/0', 
'/catalog/tag/categories/1/categories/1', 
'/catalog/tag/categories/2', 
'/catalog/tag/categories/2/categories/0', 
'/catalog/tag/categories/2/categories/1', 
'/catalog/tag/categories/2/categories/2', 
'/catalog/tag/categories/2/categories/3', 
'/catalog/tag/categories/2/categories/7', 
'/catalog/tag/categories/2/categories/8', 
'/catalog/tag/categories/2/categories/9'
'/catalog/tag/categories/2/categories/10', 
'/catalog/tag/categories/2/categories/11', 
'/catalog/tag/categories/2/categories/14', 
'/catalog/tag/categories/2/categories/15', 
'/catalog/tag/categories/2/categories/16', 
'/catalog/tag/categories/2/categories/17'];

In python, I can sort like below.

import re

def natural_sort(l):
   convert = lambda text: int(text) if text.isdigit() else text.lower()
   alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
   print(sorted(l, key=alphanum_key))

What I've tried is below..

var reA = /[^a-zA-Z]/g;
var reN = /[^0-9]/g;

function sortAlphaNum(a, b) {
  var aA = a.replace(reA, "");
  var bA = b.replace(reA, "");
  if (aA === bA) {
    var aN = parseInt(a.replace(reN, ""), 10);
    var bN = parseInt(b.replace(reN, ""), 10);
    return aN === bN ? 0 : aN > bN ? 1 : -1;
  } else {
    return aA > bA ? 1 : -1;
  }
}

console.log(arr.sort(sortAlphaNum));

but the result was different.

like this..

['/catalog/tag/categories/0', 
'/catalog/tag/categories/1', 
'/catalog/tag/categories/2', 
'/catalog/tag/categories/0/categories/0', 
'/catalog/tag/categories/0/categories/1', 
'/catalog/tag/categories/1/categories/0', 
'/catalog/tag/categories/1/categories/1', 
'/catalog/tag/categories/2/categories/0', 
'/catalog/tag/categories/2/categories/1', 
'/catalog/tag/categories/2/categories/2', 
'/catalog/tag/categories/2/categories/3', 
'/catalog/tag/categories/2/categories/7', 
'/catalog/tag/categories/2/categories/8', 
'/catalog/tag/categories/2/categories/9'
'/catalog/tag/categories/2/categories/10', 
'/catalog/tag/categories/2/categories/11', 
'/catalog/tag/categories/2/categories/14', 
'/catalog/tag/categories/2/categories/15', 
'/catalog/tag/categories/2/categories/16', 
'/catalog/tag/categories/2/categories/17'];

If you can sort this like output, let me know plz.

And what I want to implement is sorting the input arr regardless of the length (like '/catalog/tag/categories/number/categories/number/categories/number...)

input value can be bigger.

I can't sort just using arr.sort(), so I uploaded this question.. Thanks

leee
  • 31
  • 5

1 Answers1

2

This kind of sorting is called "natural sort". In JavaScript, you can achieve it by creating a collator with numeric: true option:

const collator = new Intl.Collator(undefined, { numeric: true });

myArray.sort(collator.compare);
Robo Robok
  • 21,132
  • 17
  • 68
  • 126