# Multicriteria sort array

I have an array of objects that I must sort based on two criteria. I've come up with a solution but I'd like to know if there is a better way to do it.

Assume a list of devices:

[
{"battery_level": 0.45, "network_status": "ok"},
{"battery_level": 0.45, "network_status": "ok"},
{"battery_level": 0.50, "network_status": "lost"},
{"battery_level": 0.35, "network_status": "lost"},
{"battery_level": 0.75, "network_status": "ok"},
{"battery_level": 0.05, "network_status": "lost"},
{"battery_level": 0.75, "network_status": "lost"}
]


All lost devices must be on top and sorted by battery status ascending, so that it looks like this once sorted:

[
{"battery_level":0.05,"network_status":"lost"},
{"battery_level":0.35,"network_status":"lost"},
{"battery_level":0.5,"network_status":"lost"},
{"battery_level":0.75,"network_status":"lost"},
{"battery_level":0.75,"network_status":"ok"},
{"battery_level":0.45,"network_status":"ok"},
{"battery_level":0.45,"network_status":"ok"}
]


Demo here

var devices = JSON.parse(document.getElementById('devices').innerHTML),
lostDevices,
sortBatteryLevelAsc,
sortNetworkStatusLostAsc,
i;

devices.sort(function (dev0, dev1) {
return dev0.network_status === 'lost' ? -1 : 1;
});

lostDevices = devices.filter(function (dev) {
return dev.network_status === 'lost';
});

lostDevices.sort(function (dev0, dev1) {
return dev0.battery_level <= dev1.battery_level ? -1 : 1;
});

console.clear();
console.log(devices);

Array.prototype.splice.apply(devices, [0, lostDevices.length].concat(lostDevices));

console.log(devices);


Is it smart enough, or is there a smarter way to do it?

There is a better way, use a single sort function where you check on both values. If network status is different, sort on that, otherwise sort on battery power:

var devices = JSON.parse(document.getElementById('devices').innerHTML);

function sortDevicesByStatusAndPower(a, b) {
var aStatus = a.network_status,
bStatus = b.network_status;
if( aStatus != b.network_status )
return aStatus < bStatus ? -1 : 1;
else
return a.battery_level - b.battery_level;
}

console.clear();

console.log(devices.sort( sortDevicesByStatusAndPower ));


I built a jsbin for this: http://jsbin.com/gesoq/1/edit

Finally, storing the JSON iside a script tag is .. novel, not sure it is the best approach.

• Yes it was just to test my algorithm, in real situation I use an API with angular, but I considered it not relevant to the related problem. Apr 15 '14 at 12:03

If you're looking for tersity, here's another;

devices.sort(function(a, b) {
return a.network_status === b.network_status
? a.battery_level - b.battery_level
: a.network_status > b.network_status;
}