Sign up ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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?

share|improve this question

2 Answers 2

up vote 4 down vote accepted

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.

share|improve this answer
    
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. –  aduch 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;
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.