Christian R Christian R - 6 months ago 64
Javascript Question

Underscore: sortBy() based on multiple attributes

I am trying to sort an array with objects based on multiple attributes. I.e if the first attribute is the same between two objects a second attribute should be used to comapare the two objects. For example, consider the following array:

var patients = [
[{name: 'John', roomNumber: 1, bedNumber: 1}],
[{name: 'Lisa', roomNumber: 1, bedNumber: 2}],
[{name: 'Chris', roomNumber: 2, bedNumber: 1}],
[{name: 'Omar', roomNumber: 3, bedNumber: 1}]

Sorting these by the
attribute i would use the following code:

var sortedArray = _.sortBy(patients, function(patient) {
return patient[0].roomNumber;

This works fine, but how do i proceed so that 'John' and 'Lisa' will be sorted properly?


Here's a hacky trick I sometimes use in these cases: combine the properties in such a way that the result will be sortable:

var sortedArray = _.sortBy(patients, function(patient) {
  return [patient[0].roomNumber, patient[0].name].join("_");

However, as I said, that's pretty hacky. To do this properly you'd probably want to actually use the core JavaScript sort method:

patients.sort(function(x, y) {
  var roomX = x[0].roomNumber;
  var roomY = y[0].roomNumber;
  if (roomX !== roomY) {
    return compare(roomX, roomY);
  return compare(x[0].name, y[0].name);

// General comparison function for convenience
function compare(x, y) {
  if (x === y) {
    return 0;
  return x > y ? 1 : -1;

Of course, this will sort your array in place. If you want a sorted copy (like _.sortBy would give you), clone the array first:

function sortOutOfPlace(sequence, sorter) {
  var copy = _.clone(sequence);
  return copy;

Out of boredom, I just wrote a general solution (to sort by any arbitrary number of keys) for this as well: have a look.