Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort array by first character then number in JavaScript

There is list of object contains data like below:

[
    {name: 'Foo 1'},
    {name: 'Foo 14'},
    ..
    {name: 'Foo 2'},
    {name: 'Bar 1'},
    {name: 'Bar 15'},
    ...
    {name: 'Bar 2'},
]

I need to sort this as

[
    {name: 'Bar 1'},
    {name: 'Bar 2'},
    ...
    {name: 'Bar 15'},
    {name: 'Foo 1'},
    {name: 'Foo 1'},
    ...
    {name: 'Foo 12'},
]

With classic character sorting 'Foo 14' gets ahead of 'Foo 2' so I need to sort by letter and numbers.

value pattern: There might be multiple words but always ends with number like "word word .. number"

like image 584
TyForHelpDude Avatar asked Dec 22 '22 14:12

TyForHelpDude


2 Answers

You could use Collator#compare for this. The compare() method compares two strings according to the sort order of the Intl.Collator object. Just make sure you pass an options object where you set numeric to true:

const collator = new Intl.Collator("en", {
  numeric: true,
  sensitivity: "base",
});

const arr = [
  { name: "Foo 1" },
  { name: "Baz 21" },
  { name: "Foo 14" },
  { name: "Foo 2" },
  { name: "Bar 1" },
  { name: "Baz 10" },
  { name: "Bar 15" },
  { name: "Bar 2" },
  { name: "Baz 1" },
  { name: "Baz 2" },
];

const sorted = arr.sort((a, b) => collator.compare(a.name, b.name));

console.log(sorted);
like image 74
Zsolt Meszaros Avatar answered Dec 29 '22 21:12

Zsolt Meszaros


It appears that Intl.Collator is almost twice as fast as localeCompare. So, I would use @ZsoltMeszaros answer.


Using String.prototype.localeCompare():

const arr = [
  { name: "Foo 1" },
  { name: "Baz 21" },
  { name: "Foo 14" },
  { name: "Foo 2" },
  { name: "Bar 1" },
  { name: "Baz 10" },
  { name: "Bar 15" },
  { name: "Bar 2" },
  { name: "Baz 1" },
  { name: "Baz 2" },
];

console.log(arr.sort((a,b)=>a.name.localeCompare(b.name,'en',{numeric : true})))
like image 27
Tawfik Nasser Avatar answered Dec 29 '22 22:12

Tawfik Nasser