Is there an easy way (i.e. using the spaceship operator) to define comparison in Ruby based on two different attributes? I.e. If I have a class that contains two attributes, attr1 and attr2, is there a Rubyesque way of comparing two instances of this class on attr1, and if they're equal then compare them on attr2?
This is an easily extendible (to more attributes) way:
def <=>(other)
[self.attr1, self.attr2] <=> [other.attr1, other.attr2]
end
The whole point of the comparable mixin is to provide a definition for the spaceship (comparison) operator. So if you want to do a comparison across two attributes, then do it. Here's an overly verbose example:
def <=>(obj)
comparison = self.attr1 <=> obj.attr1
if comparison == 0
return self.attr2 <=> obj.attr2
else
return comparison
end
end
Obviously the above assumes attr1
, and attr2
both have definitions for the spaceship operator. As well you'll need to determine what constitutes greater than, and less than, which is likely a bit difficult across two attributes. Which suggests that comparable may not be the proper code for your scenario.
def <=>(obj)
self.attr1 <=> obj.attr1 == 0 ? self.attr2 <=> obj.attr2 : self.attr1 <=> obj.attr1
end
a <=> b :=
if a < b then return -1
if a = b then return 0
if a > b then return 1
if a and b are not comparable then return nil <= I wanted this
Steenslag's solution wasn't giving me the nil when 'not comparable'.
Added extra line for coping with 'not comparable':
def <=> other
return nil unless other.is_a?(self.class)
[self.attr1, self.attr2] <=> [other.attr1, other.attr2]
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With