1

How can I sort an object array which has null and undefined values using javascript. My target is to show items that has property of "jobTitle" first, order them by rating, then items with no "jobTitle" ordered by rating again. Data:

data = [
  {name: 'John', rating: null},
  {name: 'Ethel', rating: 1.34, jobTitle: 'engineer'},
  {name: 'Abba', rating: 5.44},
  {name: 'Harry', rating: 0.44, jobTitle: 'plumber'}
]

After data is sorted by jobTitle and then by rating it should be like:

[
  {name: 'Ethel', rating: 1.34, jobTitle: 'engineer'},
  {name: 'Harry', rating: 0.44, jobTitle: 'plumber'},
  {name: 'Abba', rating: 5.44},
  {name: 'John', rating: null}
]

I have tried many variations like:

data.sort(function (a, b) {
  var x = a[key]; var y = b[key];
  return ((x > y) ? -1 : ((x < y) ? 1 : 0));
});

but it did not work for undefined and null values. I do not want to use low quality solutions like creating new arrays, fill with data and merge them. I want to achieve that in single method if possible.

EDIT

In general response should show first those who has jobTitle orderd by rating AND then those who don't have jobTitle ALSO ordered by rating.

6
  • firstly, that's not JSON - so ... should undefined (which won't ever appear in JSON) and null be treated as high or low? oh, I see, high, right Commented May 1, 2020 at 7:29
  • @JaromandaX this is JSON. Null should be at the bottom, so I guess low Commented May 1, 2020 at 7:32
  • this is NOT JSON ... data = ... means it's just an array of objects - you may have retrieved it from some API as JSON, but it's been parsed and is no longer JSON Commented May 1, 2020 at 7:35
  • @IntoTheDeep JSON and JS native objects are not the same, Here you can read more about it. Commented May 1, 2020 at 8:02
  • @JaromandaX seems correct to me Commented May 1, 2020 at 8:35

3 Answers 3

4

You can check for each condition, and return the response to the callback in expected manner.

data = [
  {name: 'John', rating: null},
  {name: 'Ethel', rating: 1.34, jobTitle: 'engineer'},
  {name: 'Abba', rating: 5.44},
  {name: 'Harry', rating: 0.44, jobTitle: 'plumber'}
];


data.sort((a, b) => {
  if(a.jobTitle && b.jobTitle) {
    return (b.rating || 0) - (a.rating || 0);
  } else if(a.jobTitle || b.jobTitle) {
    return !(a.jobTitle) - !(b.jobTitle)
  } else  {
    return (b.rating || 0) - (a.rating || 0);
  }
});
console.log(data)

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

4 Comments

sorry @AZ_ - you're right, read my response to you in my question - some meddling person critiqued my first answer to tell me "sort by job title first" ... whereas it's not that at all - I've removed my comment, and if the OP could just un-accept my answer, I'll delete the abomination :p
and I was scratching my head :D
@AZ_ I have accepted this answer. Out of scope: if I want to show those with jobTitle after those who haven't whant must I change? THank you
@IntoTheDeep you can simply change the ! to !! i.e. !!(a.jobTitle) - !!(b.jobTitle) or just switch the a and b i.e. return !(b.jobTitle) - !(a.jobTitle)
0

I would recommend splitting your code up in 2 sorts and use them in sequence.

let result = [
  {name: 'John', rating: null},
  {name: 'Peter', rating: null},
  {name: 'Harry', rating: 0.44, jobTitle: 'plumber'},
  {name: 'Harry', rating: 0.50, jobTitle: 'plumber'},
  {name: 'Anderson', rating: 1.34, jobTitle: 'mascot'},
  {name: 'Ethel', rating: 1.34, jobTitle: 'engineer'},
  {name: 'Abba', rating: 5.44}
]
result.sort(by_rating);
result.sort(by_job_title);
console.log(result)

function by_job_title(a, b ){
  if( typeof a.jobTitle === 'undefined' && typeof a.jobTitle === 'undefined' ) return 0;
  if( typeof b.jobTitle === 'undefined' ) return -1;
  if( typeof a.jobTitle === 'undefined' ) return 1;
  
  let title_a = a.jobTitle.toLowerCase();
  let title_b = b.jobTitle.toLowerCase();
  
  if( title_a === title_b ) return 0;
  if( title_a > title_b ) return 1;
  else return -1;
}

function by_rating( a, b ) {
  // notice that this works with null, only because null will be casted to 0
  if( a.rating === b.rating ) return 0;
  if( a.rating > b.rating ) return -1;
  else return 1;
}

Comments

-3

In your sort function you can check if a value is null or undefined and return 1 in that case, so it's sorted to the end of the array. As a sidenote: You're sorting an array, not a JSON string. A JSON string can not contain the undefined primitive value, while it is valid Javascript.

data.sort(function (a, b) {
  var x = a[key];
  var y = b[key];
  if (x === null || x === undefined) {
    return 1;
  }
  return y - x;
});

3 Comments

key is undefined
I copied your example, I don't know where you got the key from. You should be able to figure it out.
you return 1 meaning "greater than" comparing a null with null? Won't that make the algorithm crazy? Wouldn't it be 0?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.