0

I am trying to perform a sort_by on a hash, but whenever I have a nil value I get: comparison of DateTime with nil failed

My goal is to perform a nil check (.present?) on x[:last_posted_at] inside the sort_by method. Is that possible? Example code:

posts = [
  { "name"=>"Alice", "last_posted_at"=> some_datetime },
  { "name"=>"Bob",   "last_posted_at"=> nil},
  { "name"=>"Clark", "last_posted_at"=> some_datetime - 1}
]

# expected result
posts.sort_by.{ |x| x[:last_posted_at] } #compare only if value is not nil
  #=> [{"name"=>"Alice", "last_posted_at"=> some_datetime},
  #    {"name"=>"Clark", "last_posted_at"=> some_datetime - 1},
  #    {"name"=>"Bob",   "last_posted_at"=> nil}]

I looked into the sort_by documentation and some of the posts here in stackoverflow, but I cannot find my answer. Any help or links are welcome! Thanks in advance!

2 Answers 2

1

I like Schwern's approach. But if there are more records without a date then another option might be to separate record without dates from the records with dates and only sort thoses with a date like this:

posts
  .partition { |v| v['last_posted_at'] }                   # separate by date presence
  .tap { |v| v.first.sort_by! { |v| v['last_posted_at']} } # only sort entries with a date
  .flatten                                                 # combine into one list again
Sign up to request clarification or add additional context in comments.

1 Comment

Indeed this is more similar to the approach I am going for. Thank you too!
1

Use presence to return the value or nil, and || to return a default value if it is blank.

# Something sufficiently old to be older than any other time.
nil_time = Time.at(0)
posts.sort_by.{ |x|
  x[:last_posted_at].presence || nil_time
}

Note: DateTime is deprecated.

2 Comments

Thanks! I think this is exactly what I am looking for. I wrote datetime intuitively. Time is what I use for my project
You might want to incorporate the element's index to keep their relative positions for identical time values (i.e. make the sort stable) via posts.sort_by.with_index { |x, i| [x[:last_posted_at].presence || nil_time, i] }

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.