Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > is there a shorter way to compare these 2 objects?

Reply
Thread Tools

is there a shorter way to compare these 2 objects?

 
 
Lowell Kirsh
Guest
Posts: n/a
 
      08-18-2005
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
 
Reply With Quote
 
 
 
 
James Edward Gray II
Guest
Posts: n/a
 
      08-18-2005

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



 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      08-18-2005
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

 
Reply With Quote
 
James Edward Gray II
Guest
Posts: n/a
 
      08-18-2005
On Aug 17, 2005, at 10:33 PM, James Edward Gray II wrote:

> 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


 
Reply With Quote
 
Lowell Kirsh
Guest
Posts: n/a
 
      08-18-2005
James Edward Gray II wrote:
> def <=>( other )
> [@a, @b, @c, @d] <=> [other.a, other.b, other.c, other.d]
> end


Great, this is *exactly* what I was looking for
 
Reply With Quote
 
Lowell Kirsh
Guest
Posts: n/a
 
      08-18-2005
Those solutions are definitely cool but I find James' to be more
readable so that's what I'll use.

Robert Klemme wrote:
> 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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Is there a shorter, more elegant way to write this deep hashlookup statement Dr.Ruud Perl Misc 1 02-21-2013 04:37 PM
Re: Is there a shorter, more elegant way to write this deep hash lookup statement Ted Zlatanov Perl Misc 0 02-21-2013 04:35 PM
Re: Is there a shorter, more elegant way to write this deep hashlookup statement C.DeRykus Perl Misc 0 02-19-2013 07:40 PM
Re: Is there a shorter, more elegant way to write this deep hash lookup statement George Mpouras Perl Misc 0 02-17-2013 12:07 PM
Is there a shorter solution ? HumbleWorker C Programming 20 08-12-2011 04:06 PM



Advertisments