Christian R - 1 month ago 15x
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
roomNumber
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);
copy.sort(sorter);
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.