Javascript sort array of objects by a boolean property

JavascriptSorting

Javascript Problem Overview


See edit at end for actual problem.

Ok, I have this scenario:

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]

Then if I do this:

a.sort(function(a,b){return !a && b});

It gives me this:

[false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]

It's sorta doing a sort... but not quite... :(

How do I sort this array?

EDIT:

If you are wondering why I did not use just a.sort() is because my actual array is of objects, not a plain array like the one I posted. The real one has elements that look like [{xx:true},{xx:false},...]

Javascript Solutions


Solution 1 - Javascript

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
    
    
    a.sort(function(x, y) {
        // true values first
        return (x === y)? 0 : x? -1 : 1;
        // false values first
        // return (x === y)? 0 : x? 1 : -1;
    });
    
    console.log(a);

You must return 0 when a and b both have the same value, -1 if a is true and 1 otherwise.

Solution 2 - Javascript

To prevent implicit type conversion (which languages like TypeScript don't like), you can use Number() to explicitly convert the boolean to a number:

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
a.sort(function(x, y) {
   return Number(x) - Number(y);
});
console.log(a);

Or using arrow functions:

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
a.sort((x, y) => Number(x) - Number(y));
console.log(a);

Solution 3 - Javascript

a simpler way:

a = [{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false}];

a.sort(function(a,b){return a.xx-b.xx});

console.log(a);

you can call a.reverse() after the sort() if you want it sorted the other way..

EDIT: edited to reflect updated question of sorting an array of objects instead of an array of booleans.

Solution 4 - Javascript

An array does not have any equal positions, so why not leave away the equals check, and always return either -1 or 1. This approach works well with TS.

a.sort(x => x ? -1 : 1)

Note: I am a bit concerned how this affects internals of the sort function, but it seems to do the trick.

If you want to reverse sort

a.sort(x => !x ? -1 : 1)

Solution 5 - Javascript

Simple solution:

[true, false, true, false].sort( (a,b) => b - a)

Solution 6 - Javascript

PFB the solution worked for me in Typescript Angular 2 as well,

  let a = [{aa:"1",xx:true},{aa:"10",xx:false},{aa:"2",xx:true},{aa:"11",xx:false},{aa:"3",xx:true},{aa:"12",xx:false},{aa:"4",xx:true},{aa:"13",xx:false},{aa:"5",xx:true},{aa:"14",xx:false},{aa:"6",xx:true},{aa:"15",xx:false},{aa:"7",xx:true},{aa:"16",xx:false},{aa:"8",xx:true},{aa:"17",xx:false},{aa:"9",xx:true},{aa:"18",xx:false}];

    //a.sort(function(a,b){return a.xx-b.xx});
    a.sort(function (x, y) {
        // true values first
        return (x.xx === y.xx) ? 0 : x ? -1 : 1;
        // false values first
        // return (x === y)? 0 : x? 1 : -1;
    });
    return JSON.stringify(a);

Solution 7 - Javascript

I wanted to see if I could do it without using the ? : operator, just for fun.

Note

This works on all sortable data types (strings, numbers), not just raw booleans. I'm not sure if this is faster than ? : and it's more convoluted. I just get sick of conditionals so it's just personal preference.

  var b = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
  .sort((a,b) => Number(a > b) * 2 - 1);

I can turn that into a utility function and give it a meaningful name:

  var sortOrder = {
    asc: (a,b) => Number(a > b) * 2 - 1,
    desc: (a,b) => Number(a < b) * 2 - 1
  }

so then I can:

  var b = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
  .sort(sortOrder.asc);

Solution 8 - Javascript

I also ran into this issue, here is my part, I hope it helps:

orders.sort((x, y) => {
   if (x === y) return 0;
   if (x) return -1;
   return 1;
});

Solution 9 - Javascript

A pretty simple solution for the comparison function is to check if a < b, this gives 0 or 1 when converted to a number. We then want to map 0 to -1 and 1 to 1. To do that you can just multiply by 2 then subtract 1.

data.sort(function (a, b) {
  return (a < b) * 2 - 1
}

or just

data.sort((a, b) => (a < b) * 2 - 1)

Problem sorted!

If any of your values are null they are treated as false (null*2 === 0) and any value that is undefined will become NaN (undefined*2 === NaN) which should make it last in either sort direction.

Solution 10 - Javascript

a=[true,false,true,false,true];
 
a.sort(function(x, y) {
      a1=x?1:0
      b1=y?1:0
return a1-b1
    });

Solution 11 - Javascript

A boolean array with enough entries to represent all transitions i.e. true to true, true to false, false to false, false to true.

var boolarray = [true, false, true, true, false, false, true]
boolarray.sort( (a,b) => !(a ^ b) ? 0 : a ? -1 : 1)

The sort inverts the xor of the inputs. If the inputs are the same then return 0, if they are not then, if the 'a' input is true 'b' must be false so return -1, and vice versa return 1.

'a' and 'b' booleans are sorted when they differ and are ignored when the same.

To use this method with objects just use the object member names for the sort arguments:

var objarray = [{xx:true}, {xx:false}, {xx:true}, {xx:true}, {xx:false}, {xx:false}, {xx:true}]
objarray.sort( (a,b) => !(a.xx ^ b.xx) ? 0 : a.xx ? -1 : 1)

Solution 12 - Javascript

I got typescript errors on the return (x.xx === y.xx) ? 0 : x ? -1 : 1;

This is my solution when you want to sort on a boolean property

this.mediaList.sort( (a: MediaAutosubscriptionModel, b: MediaAutosubscriptionModel) => {
	let status1: number = a.status === StatusEnum.ACTIVE ? 1 : 0;
	let status2: number = b.status === StatusEnum.ACTIVE ? 1 : 0;
	let comparison: number = 0;
	let direction: number = this.sortDirection === SortDirectionsEnum.ASC ? -1 : 1;
	if (status1 > status2) {
		comparison = direction;
	} else if (status1 < status2) {
		comparison = -1 * direction;
	}
	    return comparison;
	});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPCoelhoView Question on Stackoverflow
Solution 1 - Javascriptc.P.u1View Answer on Stackoverflow
Solution 2 - JavascriptsroesView Answer on Stackoverflow
Solution 3 - JavascriptdandavisView Answer on Stackoverflow
Solution 4 - JavascriptKristjan LiivaView Answer on Stackoverflow
Solution 5 - JavascriptСергей МисникView Answer on Stackoverflow
Solution 6 - JavascriptdreamdeveloperView Answer on Stackoverflow
Solution 7 - JavascripttoddmoView Answer on Stackoverflow
Solution 8 - JavascriptspedyView Answer on Stackoverflow
Solution 9 - JavascriptMattCochraneView Answer on Stackoverflow
Solution 10 - JavascriptSIDDHANT JOHARIView Answer on Stackoverflow
Solution 11 - JavascriptroyView Answer on Stackoverflow
Solution 12 - JavascriptchriscrosswebView Answer on Stackoverflow