DEV Community

Aviskar KC
Aviskar KC

Posted on

Array.sort gotcha: Case of the missing key

When you are working as a web developer, you will have to sort an array in ascending or descending order at some point in time.

To sort arrays based on some value, we can use the built-in Array.prototype.sort() function which works as follows:

// sort in ascending order
array.sort(function (a, b) {
  if (a < b) {
     return -1;
  }

  if (a > b) {
     return 1;
  }

  if (a === b) {
     return 0;
  }
});

// sort in descending order
array.sort(function (a, b) {
  if (a < b) {
     return 1;
  }

  if (a > b) {
     return -1;
  }

  if (a === b) {
     return 0;
  }
});

Since the array.prototype.sort() function depends on positive, negative and zero values to determine the order of elements, we can simplify the above logic if we are working with numbers:

// sort in ascending order
array.sort(function (a, b) {
  return a - b;
});

// sort in descending order
array.sort(function (a, b) {
  return b - a;
})

So if we are sorting an array of object, in ascending order, our code will look like this:

let array = [{ id: 1, value: 10 }, { id: 2, value: 2 }, { id: 3, value: 5 }];

// sort in ascending order:
array.sort(function(a, b) {
  return a.value - b.value;
});

// Output => [{ id: 2, value:  3 }, { id: 3, value: 5 }, { id: 1, value: 10 }];

But imagine I introduce a new element into the mix, which doesn't have the key value:

// New element { id: 4 } which doesn't have the key `value`
let array = [{ id: 1, value: 10 }, { id: 4 }, { id: 2, value: 2 }, { id: 3, value: 5 }]; 

// sort in ascending order:
array.sort(function(a, b) {
  return a.value - b.value;
});

// Output => [{ id: 1, value: 10 }, { id: 4 }, { id: 2, value: 2 }, { id: 3, value: 5 }];

Because our new element doesn't have the key value, accessing it will return undefined. Now, trying to subtract a number with undefined will result in NaN and cause our sort function to not work as intended.

I recently got stung by this gotcha and worked around it by assigning 0 to the missing values:

// New element { id: 4 } which doesn't have the key `value`
let array = [{ id: 1, value: 10 }, { id: 4 }, { id: 2, value: 2 }, { id: 3, value: 5 }]; 

// sort in ascending order:
array.sort(function(a, b) {
  const valueA = a.value || 0;
  const valueB = b.value || 0;

  return valueA - valueB;
});

// Output => [{ id: 4 }, { id: 2, value: 2 }, { id: 3, value: 5 }, { id: 1, value: 10 }];

As I was ordering array of objects in descending order by likes, this worked perfectly for my use case.

Top comments (4)

Collapse
 
zenulabidin profile image
Ali Sherief

Do JS arrays have a comparison method that can be passed to array.prototype.sort() so we don't have to write one each time?

Collapse
 
aviskarkc10 profile image
Aviskar KC

are you talking about something like this?

function compare(a ,b) {
   return a - b;
}

array.sort(compare)

I didn't quite get your question but you can read more about the sort function here:
developer.mozilla.org/en-US/docs/W...

Collapse
 
zenulabidin profile image
Ali Sherief

I was thinking that arrays could be sorted using array.sort() without specifying a compare function as an argument, and then sort would internally use a compare function like the one above.

Thread Thread
 
aviskarkc10 profile image
Aviskar KC

Yes, arrays can be sorted by doing just array.sort for arrays that contains numbers/strings. But when you want to sort an array of objects, you will need to specify the condition for sorting elements.