TyForHelpDude
TyForHelpDude

Reputation: 5002

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"

Upvotes: 4

Views: 833

Answers (2)

Tawfik Nasser
Tawfik Nasser

Reputation: 1124

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})))

Upvotes: 2

Zsolt Meszaros
Zsolt Meszaros

Reputation: 23160

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);

Upvotes: 8

Related Questions