is there a shorter way to compare these 2 objects?

L

Lowell Kirsh

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:

if (@a <=> rhs.a) != 0
@a <=> rhs
elsif (@b <=> rhs.b) != 0
@b <=> rhs.b
elsif ....

Is there a more concise way of doing this? I know this code isn't the
ugliest, but something in my gut tells me there's got to be a better
way. Especially if we have more than 4 variables.

lowell
 
J

James Edward Gray II

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
 
R

Robert Klemme

James said:
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
1
=> nil


Kind regards

robert
 
J

James Edward Gray II

Arrays are Comparable...

I misspoke a little here. Arrays are NOT Comparable, but the DO
implement <=>(), which is all you need here.

James Edward Gray II
 
L

Lowell Kirsh

Those solutions are definitely cool but I find James' to be more
readable so that's what I'll use.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top