5

I have an array of objects as follows:

c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}]

I want to kind-of sort them by the objects having values first then objects with null.

What I tried is:

c.sort(function(b) { return b.a ? -1 : 1 })

OUTPUT

[{a: 2}, {a: 50}, {a: 1}, {a: 12}, {a: null}, {a: null}]

EXPECTED OUTPUT

[{a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}, {a: null}]

How can I achieve this?

3
  • @GokulanPH Yes, I can. I just haven't used it in my question, so didn't tag it Commented Jun 28, 2017 at 12:47
  • 1
    The Array#sort function has an arity of 2, it has an a and b argument for comparison. Commented Jun 28, 2017 at 12:48
  • Also, beware of sort stability: stackoverflow.com/questions/1517793/… Commented Jun 28, 2017 at 12:54

8 Answers 8

7

This will put nulls and other falsy values to the end of the list:

c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];
c.sort((x, y) => !!y.a - !!x.a);

console.log(c);

However, since you don't really sort anything, you can just split the list into two parts an rejoin them:

c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];

r = [
  ...c.filter(x => x.a !== null),
  ...c.filter(x => x.a === null)
]

console.log(r)

This also doesn't rely on the sort function being stable.

Sign up to request clarification or add additional context in comments.

2 Comments

it moves zero values to the bottom.
The filter option is much better than using sort in this use case, it avoids any stability problems.
3

You could test the value. If null, then take the delta of the comparison.

var c = [{ a: null }, { a: 12 }, { a: 1 }, { a: 50 }, { a: 2 }, { a: null }];

c.sort(function (a, b) {
    return (a.a === null) - (b.a === null);
});

console.log(c);
.as-console-wrapper { max-height: 100% !important; top: 0; }

For a stable sort, you could use sorting with map and use the indices as second sort option.

// the array to be sorted
var list = [{ a: null }, { a: 12 }, { a: 1 }, { a: 50 }, { a: 2 }, { a: null }];

// temporary array holds objects with position and sort-value
var mapped = list.map(function(el, i) {
    return { index: i, value: el.a === null};
});

// sorting the mapped array containing the reduced values
mapped.sort(function(a, b) {
    return a.value - b.value || a.index - b.index;
});

// container for the resulting order
var result = mapped.map(function(el){
    return list[el.index];
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

1 Comment

Awesome solution
1

const c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];

let result = [...c.filter(_=>_["a"]!==null),...c.filter(_=>_["a"]===null)];

console.log(result);

Comments

1

Try with return !a.a - !b.a .valid object goes first

var c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];

c.sort(function (a, b) {
    return !a.a - !b.a
});
console.log(c);

Comments

1

That way ?

c=[{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}];
c.sort(function(a,b){ return a.a===null ? 1:-1 })
console.log(c);

Edited

1 Comment

This sorts the objects, I just want to push objects with null values to last
1

var c = [{
  a: null
}, {
  a: 12
}, {
  a: 1
}, {
  a: 50
}, {
  a: 2
}, {
  a: null
}];

c.sort(function(a, b) {
  return (a.a !== null) ? 0 : 1;
});
console.log(c);

Returning 0 in the sort function will keep the order as it is.

If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements.

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

3 Comments

Although @Xotic750's comment "The Array#sort function has an arity of 2, it has an a and b argument for comparison." is right, but this answer worked for me.
maybe i see wrong, but in edge, i see a null value at top and one at bottom. it heavily rely on just one side of the compairing between two vaules.
@vsr, still the same problem.
0

It is not perfect but still works,cheers!

var c = [{a: null}, {a: 12}, {a: 1}, {a: 50}, {a: 2}, {a: null}]

c.sort(function(object1,object2){

  
  if(object1.a === null && object2.a !== null){return 1}
  
  if([object1.a,object2.a].every((a)=>a === null) ||      
     [object1.a,object2.a].every((a)=>a !== null)
     ){return 0}
  
  if(object1.a !== null && object2.a === null){return -1}
  


})

console.log(c);

Comments

0

Here's a case of sorting a Date with null value at the end if exists:

userSortList = users.sort((a, b) => {
    if (b.lastConnectionDate === null || a.lastConnectionDate) {
        return -1
    } else {
        return (
            new Date(b.lastConnectionDate) - new Date(a.lastConnectionDate)
        )
    }
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.