Daft Daft - 1 month ago 6
Javascript Question

Move all items, with a certain value, to end of array

I have an array of objects, there's a

state
value on each object.

I would like to order the array so that any obejects with a state of either
healthy
or
unhealthy
are pushed to the end of the array.

I'd like to group all
healthy
items together and all
unhealthy
items together also.

var people = [
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'other'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'unhealthy'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'other'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'healthy'
}
{
name: 'XXX',
state: 'other'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'other'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'unhealthy'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'healthy'
}
];


I would like the final array to look like this:

var people = [
{
name: 'XXX',
state: 'other'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'other'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'other'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'other'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'dead'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'healthy'
},
{
name: 'XXX',
state: 'unhealthy'
},
{
name: 'XXX',
state: 'unhealthy'
}
];


I've attempted the following, but for some reason, some items in the array are missed.

I think possibly as I'm pushing items to the bottom, the index of all other items changes and I'm missing some?

_.each(people, function(p){
if(p.state === 'healthy'){
var arr_idx = people.indexOf(p);
people.push(people.splice(arr_idx, 1)[0]);
}
});

_.each(people, function(p){
if(p.state === 'unhealthy'){
var arr_idx = people.indexOf(p);
people.push(people.splice(arr_idx, 1)[0]);
}
});

Answer

You could use an object for the sort order.

var people = [{ name: 'XXX', state: 'healthy' }, { name: 'XXX', state: 'other' }, { name: 'XXX', state: 'healthy' }, { name: 'XXX', state: 'dead' }, { name: 'XXX', state: 'unhealthy' }, { name: 'XXX', state: 'healthy' }, { name: 'XXX', state: 'dead' }, { name: 'XXX', state: 'healthy' }, { name: 'XXX', state: 'dead' }, { name: 'XXX', state: 'other' }, { name: 'XXX', state: 'dead' }, { name: 'XXX', state: 'healthy' }, { name: 'XXX', state: 'other' }, { name: 'XXX', state: 'healthy' }, { name: 'XXX', state: 'dead' }, { name: 'XXX', state: 'other' }, { name: 'XXX', state: 'dead' }, { name: 'XXX', state: 'unhealthy' }, { name: 'XXX', state: 'dead' }, { name: 'XXX', state: 'healthy' }];

people.sort(function (a, b) {
    var order = { healthy: 1, unhealthy: 2 };              // easy to maintain
    return (order[a.state] || 0) - (order[b.state] || 0);  // return delta of order
});

console.log(people);