sorting a ruby array of objects by an attribute that could be nil

How about in Child defining <=> to be based on category.position if category exists, and sorting items without a category as always greater than those with a category?

class Child
  # Not strictly necessary, but will define other comparisons based on <=>
  include Comparable   
  def <=> other
    return 0 if !category && !other.category
    return 1 if !category
    return -1 if !other.category
    category.position <=> other.category.position
  end
end

Then in Parent you can just call children.sort.


To be fair, I'm not very familiar with Ruby, so take this as more of an algorithm idea rather than a code one... and rewrite the ?: operator as whatever Ruby has that's cleaner.

Can't you just check for nil in the comparison:

class Parent
  def sorted_children
     children.sort{|a,b|( a and b ) ? a <=> b : ( a ? -1 : 1 ) }
  end
end

Edited to use Glenra's code, which implements the same thing as mine but in a smaller (and probably easier to read) amount of code.


I would just tweak your sort to put nil items last. Try something like this.

foo = [nil, -3, 100, 4, 6, nil, 4, nil, 23]

foo.sort { |a,b| a && b ? a <=> b : a ? -1 : 1 }

=> [-3, 4, 4, 6, 23, 100, nil, nil, nil]

That says: if a and b are both non-nil sort them normally but if one of them is nil, return a status that sorts that one larger.


I handle these kinds of things like this:

 children.sort_by {|child| [child.position ? 0 : 1,child.position || 0]}