4

I am trying to sort an array.

Ex-

let arr = [{label: "Name 5"}, {label: "Name 3"},{label: "Name 12"}, {label: "Name 10"}, {label: "First Name 5"}, {label: "Apple"}, {label: "Orange"}, {label: "water"}];


let sortedArray = arr.sort(function(a, b){
 return a.label.localeCompare(b.label);
});

console.log(sortedArray);

When I try to sort it, "Name 10" comes first but "Name 3" should come fist.

I have also tried this -

let sortedArray = arr.sort(function(a, b){
  var nameA=a.label.toLowerCase(), nameB=b.label.toLowerCase();
    if (nameA < nameB){
      return -1;
    } //sort string ascending
    if (nameA > nameB){
      return 1;
    }
   return 0; //no sorting
});

And this -

Array.prototype.reverse()
String.prototype.localeCompare()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

But still no luck. Can anyone point out whats wrong here?

Joomler
  • 2,610
  • 3
  • 30
  • 37

3 Answers3

11

Why is it not working?

You are sorting strings and the default sorting is lexicographical order. What you are looking for is sorting by natural order.

Proposed solution

You could use the options of String#localeCompare for natural sorting.

let arr = [{label: "Name 5"}, {label: "Name 3"},{label: "Name 12"}, {label: "Name 10"}, {label: "First Name 5"}, {label: "Apple"}, {label: "Orange"}, {label: "water"}];

arr.sort(function(a, b) {
   return a.label.localeCompare(b.label, undefined, { numeric: true, sensitivity: 'base' });
});

console.log(arr);
Sync
  • 3,571
  • 23
  • 30
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 1
    man that worked like charm. And I was missing `localeCompare` parameters. thanks for the help :) – Joomler Dec 19 '17 at 09:42
  • 1
    The `locales` and `options` parameters require modern browser. – Salman A Dec 19 '17 at 09:43
  • How to compare date/time as strings, for example: `13_08_2018_2115` (a time in August) and `26_07_2018_1633` (a time in July). For descending view, I am using `reviews.sort(function(a, b) { return b.date.localeCompare(a.date, undefined, { numeric: true }) })`, but the July entry is before the August entry. – user1063287 Aug 13 '18 at 12:04
  • 1
    you could convert the data to an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) compliant string and compare it like a string. – Nina Scholz Aug 13 '18 at 12:06
  • Thanks @NinaScholz , I ended up changing my app's convention (for the better) and storing date/time in MongoDB like this `new Date().toISOString()`, and then the standard `localeCompare` on the value works as desired. And then I format when displaying using the awesome `date-fns`: https://date-fns.org/v1.29.0/docs/format. – user1063287 Aug 14 '18 at 08:17
  • @Sync But this give us "Name 12" before "Name 3". How to we sort Strings numerically? – Inês Gomes Oct 25 '19 at 15:15
  • I just ran the code snippet and "Name 12" definitely comes after "Name 3". – Sync Oct 25 '19 at 15:23
1

let arr = [{label: "Name 5"}, {label: "Name 3"},{label: "Name 12"}, {label: "Name 10"}, {label: "First Name 5"}, {label: "Apple"}, {label: "Orange"}, {label: "water"}];

arr.sort(function(a, b) {
  var nameA = a.label.toUpperCase(); // ignore upper and lowercase
  var nameB = b.label.toUpperCase(); // ignore upper and lowercase
  if (nameA < nameB) {
    return -1;
  }
  if (nameA > nameB) {
    return 1;
  }

  // names must be equal
  return 0;
});

console.log(arr);
Shubham
  • 1,755
  • 3
  • 17
  • 33
1

There is a problem with your dataset.

You are sorting based on the label value which is a string. Strings are always sorted in a lexicographical order. If you would like "Name 3" to come before "Name 10" you can either use "Name 03" or better yet add another numerical attribute that will be used for sorting e.g.

{label: "Name 3", order: 3}

Yonatan Naor
  • 1,367
  • 18
  • 19