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"}
]
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?
2 Answers 2
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.
-
\$\begingroup\$ 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. \$\endgroup\$axelduch– axelduch2014年04月15日 12:03:40 +00:00Commented Apr 15, 2014 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;
}