is there a shorter way to compare these 2 objects?

Discussion in 'Ruby' started by Lowell Kirsh, Aug 18, 2005.

  1. Lowell Kirsh

    Lowell Kirsh Guest

    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
     
    Lowell Kirsh, Aug 18, 2005
    #1
    1. Advertising

  2. 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
     
    James Edward Gray II, Aug 18, 2005
    #2
    1. Advertising

  3. 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
     
    Robert Klemme, Aug 18, 2005
    #3
  4. 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
     
    James Edward Gray II, Aug 18, 2005
    #4
  5. Lowell Kirsh

    Lowell Kirsh Guest

    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 :)
     
    Lowell Kirsh, Aug 18, 2005
    #5
  6. Lowell Kirsh

    Lowell Kirsh Guest

    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
     
    Lowell Kirsh, Aug 18, 2005
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. HumbleWorker

    Is there a shorter solution ?

    HumbleWorker, Aug 6, 2011, in forum: C Programming
    Replies:
    20
    Views:
    709
    Keith Thompson
    Aug 12, 2011
  2. Dr.Ruud
    Replies:
    1
    Views:
    174
    Ted Zlatanov
    Feb 21, 2013
  3. George Mpouras
    Replies:
    0
    Views:
    161
    George Mpouras
    Feb 17, 2013
  4. C.DeRykus
    Replies:
    0
    Views:
    146
    C.DeRykus
    Feb 19, 2013
  5. Ted Zlatanov
    Replies:
    0
    Views:
    148
    Ted Zlatanov
    Feb 21, 2013
Loading...

Share This Page