James Edward Gray II wrote: > On Aug 17, 2005, at 10:16 PM, Lowell Kirsh wrote: > >> I have a class called foo and I want to make it comparable so that >> I can sort arrays of Foo. Here is the class: >> >> class Foo >> attr_accessor :a, :b, :c, :d >> def <=>(rhs); (see below); end >> end >> >> I'm assuming that the a,b,c, and d field are each Comparable. To >> compare 2 Foos, we first look at the a's and if they're not the >> same, we return the result of their comparison. If they are the >> same, we continue to compare the b's, and if they're the same we >> compare the c's, and so on until we compare the last field. So for >> my definition of <=> I have the following, which works, but I'd >> like something better/shorter: > > def <=>( other ) > [@a, @b, @c, @d] <=> [other.a, other.b, other.c, other.d] > end > > Arrays are Comparable and they compare each of their contents in > order. > > Hope that helps. > > James Edward Gray II Here are some other possible implementations using #inject... :-) require 'enumerator' Foo = Struct.new :a,:b,:c,:d class Foo include Comparable def <=>(o) members.inject(0) do |cmp,field| return cmp unless cmp == 0 send(field) <=> o.send(field) end end # alternative def <=>(o) cmp = 0 each_pair do |field, val| cmp = val <=> o.send(field) return cmp unless cmp == 0 end cmp end # alternative def <=>(o) to_enum(:each_pair).inject(0) do |cmp,(field, val)| cmp = val <=> o.send(field) return cmp unless cmp == 0 end end end >> f1 = Foo.new 1,2,3,4 => #<struct Foo a=1, b=2, c=3, d=4> >> f2 = Foo.new 1,2,3,3 => #<struct Foo a=1, b=2, c=3, d=3> >> puts f1 <=> f2 1 => nil Kind regards robert