JavaScript
Article
By Olayinka Omole

Quick Tip: How to Sort an Array of Objects in JavaScript

By Olayinka Omole

Sort an array of objects in JavaScript

If you have an array of objects that you need to sort into a certain order, the temptation might be to reach for a JavaScript library. Before you do however, rember that you can do some pretty neat sorting with the native Array.sort function. In this article I’ll show you how to sort an array of objects in JavaScript with no fuss or bother.

To follow along with this article, you will need a knowledge of basic JavaScript concepts, such as declaring variables, writing functions, and conditional statements. I’ll also be using ES6 syntax. You can get a refresher on that here: https://www.sitepoint.com/tag/es6/

Basic Array Sorting

By default, the JavaScript Array.sort function converts each element in the array to be sorted, into a string, and compares them in Unicode code point order.

const foo = [9, 2, 3, 'random', 'panda'];
foo.sort(); // returns [ 2, 3, 9, 'panda', 'random' ]

const bar = [4, 19, 30, function(){}, {key: 'value'}];
bar.sort(); // returns [ 19, 30, 4, { key: 'value' }, [Function] ]

You may be wondering why 30 comes before 4… not logical huh? Well, actually it is. This happens because each element in the array is first converted to a string, and "30" comes before "4" in Unicode order.

It is also worth noting that unlike many other JavaScript array functions, Array.sort actually changes, or mutates the array it sorts.

const baz = ['hello world', 31, 5, 9, 12];
baz.sort(); // baz array is modified
console.log(baz); // shows [12, 31, 5, 9, "hello world"]

To avoid this, you can create a new instance of the array to be sorted and modify that instead.

const baz = ['hello world', 31, 5, 9, 12];
const newBaz = baz.slice().sort(); // new instance of baz array is created and sorted
console.log(baz); // "hello world", 31, 5, 9, 12]
console.log(newBaz); // [12, 31, 5, 9, "hello world"]

Try it out

JS Bin on jsbin.com

Using Array.sort alone would not be very useful for sorting an array of objects, thankfully the function takes an optional compareFunction parameter which causes the array elements to be sorted according to the return value of the compare function.

Using Compare Functions to Sort

Lets say that a and b are the two elements being compared by the compare function. If the return value of the compare function is:

  1. less than 0 — a comes before b
  2. greater than 0  — b comes before a
  3. equal to 0  — a and b are left unchanged with respect to each other

Let’s look at a simple example with an array of numbers:

const arr = [1,2,30,4];

function compare(a, b){
  let comparison = 0;

  if (a > b) {
    comparison = 1;
  } else if (b > a) {
    comparison = -1;
  }

  return comparison;
}

arr.sort(compare);
// => 1, 2, 4, 30

This can be refactored somewhat to obtain the return value by subtracting a from b;

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

Which now makes a good candidate for an arrow function:

arr.sort((a, b) => a - b));
--ADVERTISEMENT--

Sort an Array of Objects in JavaScript

Now let’s look at sorting an array of objects. Let’s take an array of band objects:

const bands = [ 
  { genre: 'Rap', band: 'Migos', albums: 2},
  { genre: 'Pop', band: 'Coldplay', albums: 4},
  { genre: 'Rock', band: 'Breaking Benjamins', albums: 1}
];

We can use the following compare function to sort this array of objects according to genre:

function compare(a, b) {
  // Use toUpperCase() to ignore character casing
  const genreA = a.genre.toUpperCase();
  const genreB = b.genre.toUpperCase();

  let comparison = 0;
  if (genreA > genreB) {
    comparison = 1;
  } else if (genreA < genreB) {
    comparison = -1;
  }
  return comparison;
}

bands.sort(compare);

/* returns [ 
{ genre: 'Pop', band: 'Coldplay', albums: 4 }, 
{ genre: 'Rap', band: 'Migos', albums: 2 }, 
{ genre: 'Rock', band: 'Breaking Benjamins', albums: 1 } 
] */

To reverse the sorting order, you can simply invert the return value of the compare function:

function compare(a, b) {
  ...

  //invert return value by multiplying by -1
  return comparison * -1; 
}

Try it out

JS Bin on jsbin.com

Creating a Dynamic Sorting Function

Let’s finish up by making this more dynamic. Let’s create a sorting function, which you can use to sort an array of objects, whose values are either strings or numbers. This function has two parameters — the key we want to sort by and the order of the results (i.e. ascending or descending).

const bands = [ 
  { genre: 'Rap', band: 'Migos', albums: 2},
  { genre: 'Pop', band: 'Coldplay', albums: 4, awards: 13},
  { genre: 'Rock', band: 'Breaking Benjamins', albums: 1}
];

// function for dynamic sorting
function compareValues(key, order='asc') {
  return function(a, b) {
    if(!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) {
      // property doesn't exist on either object
        return 0; 
    }

    const varA = (typeof a[key] === 'string') ? 
      a[key].toUpperCase() : a[key];
    const varB = (typeof b[key] === 'string') ? 
      b[key].toUpperCase() : b[key];

    let comparison = 0;
    if (varA > varB) {
      comparison = 1;
    } else if (varA < varB) {
      comparison = -1;
    }
    return (
      (order == 'desc') ? (comparison * -1) : comparison
    );
  };
}

And this is how you’d use it:

// array is sorted by band, in ascending order by default
bands.sort(compareValues('band')); 

// array is sorted by band in descending order
bands.sort(compareValues('band', 'desc')); 

// array is sorted by albums in ascending order
bands.sort(compareValues('albums')); 

Try it out

JS Bin on jsbin.com

In the code above, the hasOwnProperty method is used to check if the specified property is defined on each object and has not been inherited via the prototype chain. If it is not defined on the objects, the function returns 0, which causes the sort order to remain as is (i.e the objects remain unchanged with respect to each other).

The typeof operator is also used to check the data type of the value of the property. This allows the function to determine the proper way to sort the array. For example, if the value of the specified property is a string, a toUpperCase method is used to convert all its characters to uppercase, so character casing is ignored when sorting.

You can adjust the above function to accommodate other data types, and any other peculiarity your script needs.

Conclusion

So there you have it — a short introduction to sorting an array of objects. Although many JavaScript libraries offer this kind of dynamic sorting ability (e.g. Underscore.js, Lodash and Sugar), as demonstrated, it’s not all that hard to implement this kind of functionality yourself.

If you have any questions or comments, I’d be glad to hear them in the comments.

This article was peer reviewed by Moritz Kröger, Giulio Mainardi, Vildan Softic and Rob Simpson. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

  • surja

    Thank you, the tutorial is useful and clear, should be helpful to those who have some problems understanding the sort and compare functions.

  • Douglas Kesi-Ayeba K

    Wow! What an awesome guide! Keep it coming please.

  • Shahroze Nawaz

    Thanks for the awesome guide this helps me understanding arrays more better

  • Oluwaniyi Dayo

    Great write up…anticipating your next post, thanks !

  • I didn’t know how the 0 part of the compare method. Thanks for writing this

  • Luís Assunção

    Nice! Thanks.

  • Mobola

    Great work. Keep it up

  • Fregene

    Really good stuff. Keep it coming.

  • Porkopek

    Nice article! Thanks!
    But, please, don’t name your variables “bar”, “foo” and “baz”. Is too messy. Sure you can find better names

    • Olayinka Omole

      Thanks for reading @porkopekperes:disqus. I’ll try to be more creative with naming in the future. :)

  • Infantito

    ¿ arr.sort((a, b) => a- b); ?
    Is it has to do with the quicksort algorithm?

  • பொன்னுச்சாமி கந்தசாமி

    This is crucial to all the webdevelopers. Really understandable, Thank you.

  • jimmy de smitz

    would be worth talking about the performance overhead of the way you are sorting, especially when sorting a large number of items.

    extracting the value you want to sort on first, then running the sort and returning the original item — i.e. using a schwartzian transform — would be more efficient. :)

  • Jason Anello

    Nice tutorial!

    On this part here:

    equal to 0  — a and b are left unchanged with respect to each other

    The sort isn’t guaranteed to be stable so “a” and “b” may or may not remain unchanged with respect to each other.

  • Thanks for the article! I found a slight typo:

    Actual:
    arr.sort((a, b) => a – b));

    Expected:
    arr.sort((a, b) => (a – b));

Recommended
Sponsors
Get the latest in JavaScript, once a week, for free.