0

I have this function:

tests.sort(function (a, b) {
   var diff = a.title.localeCompare(b.title);
   return diff == 0 ? b.modifiedDate.localeCompare(a.modifiedDate) : diff;
});

I am using it to sort the tests array first by title and then by modifiedDate. The code was working but now I found it gives an error. When the modifiedDate is null and when this happens the compare fails.

How could I make it so that if the modifiedDate is null then the sort still works and places those rows after the rows with a modifiedDate that's not null?

3
  • i sometimes trash the arguments as i work down the possibilities, so you can do something like b=b.modifiedDate||0;a=a.modifiedDate||0; before the compare. Commented Mar 18, 2016 at 4:33
  • You might want to have a look at this Commented Mar 18, 2016 at 4:35
  • A simple diff == 0 && b.modifiedDate ... ? doesn't work? Commented Mar 18, 2016 at 4:36

2 Answers 2

1

Thinking off the top of my head, to sort by title and then modifiedDate with nulls last:

tests.sort(function (a, b) {
   var diff = a.title.localeCompare(b.title),
       has_modifiedDate = a.modifiedDate && b.modifiedDate && true || false; 


  if (diff === 0) {
    if (has_modifiedDate) {
      return a.modifiedDate.localeCompare(b.modifiedDate)
    }
    else {
      if (! b.modifiedDate){
        if (! a.modifiedDate)
          return 0;
        else
          return -1;
      }
      else {
        if (! a.modifiedDate)
          return 1;
        else
          return -1;
      }
    }
  }
  else 
    return diff;
});

Note: this is untested and it's very late/early here. If this is incorrect, post and I'll delete or update; but way to tired to think.

Quick dataset you can try testing with; fill in with whatever data you want:

var tests = [
  {modifiedDate:'z',    title:'foo'},
  {modifiedDate:'a',    title:'foo'},
  {modifiedDate:null,   title:'foo'},
  {modifiedDate:'a',    title:'foo'},
  {modifiedDate:'null', title:'foo'},
  {modifiedDate:'z',    title:'foo'},
  {modifiedDate:'z',    title:'bar'},
  {modifiedDate:'a',    title:'bar'},
  {modifiedDate:null,   title:'bar'}
 ];
Sign up to request clarification or add additional context in comments.

5 Comments

You could shorten it a lot (e.g. by omitting the second if (! a.modifiedDate)), but it appears to be correct
I haven't tested, but I think it's needed to push nulls to the bottom of the stack, because it's saying if they both have the same title and the next element has a modifieddate, but the current element doesn't. It looks like the if could be standalone and the else wrapper isn't needed
Just curious: why the extra true before or? a.modifiedDate && b.modifiedDate && true || false. I haven't seen this approach before.
@will it's not necessary. Without it, the variable will hold a "truthy" value, with it it will hold true. So, if you want to be more explicit in the if statement you could use the exact comparison operator and do has_modifiedDate === true. Probably has a very very micro performance benefit too, since the variable will hold a smaller value compared to a date. But, it's not necessary; it's a convention I started adopting, when I expect my is_* and has_* variables to only have true or false values.
@vol7ron I meant else { return 1; } would suffice as you already know that not both an not b are null
0

Try this:

tests.sort(function(a, b) {
    var diff = a.title.localeCompare(b.title);
    return diff == 0 ? (a.modifiedDate ? a.modifiedDate.getTime() : Infinity) - (b.modifiedDate ? b.modifiedDate.getTime() : Infinity) : diff;
})

3 Comments

You might even just do return diff || (… - …);
I'd have upvoted this (nice solution!), but I think that .modifiedDate is a string (having a .localeCompare method) not a Date object, despite the name.
@Bergi - I like the diff || (...) idea - thanks. It's cleaner.

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.