[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Array#sort -block with conditions for <=>'ing

carp __

3/8/2007 1:43:00 PM

Hello Rubyists,

I want to sort an array of objects of the same class (MyClass). The
array should be sorted by arbitrary attributes of that class, but the
problem is that one attribute can be nil.

The code looks like this:

my_array.sort {
|x,y| x.some_attribute <=> y.some_attribute
}

Naturally, if some_attribute is nil, the comparison failed (since nil is
not comparable). I am looking for something like this:

my_array.sort {
|x,y| x.some_attribute <=> y.some_attribute unless
(x.some_attribute.nil? or y.some_attribute.nil?)
}

which I have tried without having success (Error was: comparison of
MyClass with MyClass failed).

Does anyone know how to do it? Thanks in advance!

--
Posted via http://www.ruby-....

4 Answers

Farrel Lifson

3/8/2007 1:52:00 PM

0

On 08/03/07, carp __ <carp@hacksocke.de> wrote:
> Hello Rubyists,
>
> I want to sort an array of objects of the same class (MyClass). The
> array should be sorted by arbitrary attributes of that class, but the
> problem is that one attribute can be nil.
>
> The code looks like this:
>
> my_array.sort {
> |x,y| x.some_attribute <=> y.some_attribute
> }
>
> Naturally, if some_attribute is nil, the comparison failed (since nil is
> not comparable). I am looking for something like this:
>
> my_array.sort {
> |x,y| x.some_attribute <=> y.some_attribute unless
> (x.some_attribute.nil? or y.some_attribute.nil?)
> }
>
> which I have tried without having success (Error was: comparison of
> MyClass with MyClass failed).
>
> Does anyone know how to do it? Thanks in advance!

Define <=> on your class:

class MyClass
def <=>(other)
if @some_attribute.nil?
return -1
elsif @other.some_attribute.nil?
return 1
else
@some_attribute <=> other.some_attribute
end
end
end

Farrel

Brian Candler

3/8/2007 2:04:00 PM

0

On Thu, Mar 08, 2007 at 10:42:44PM +0900, carp __ wrote:
> The code looks like this:
>
> my_array.sort {
> |x,y| x.some_attribute <=> y.some_attribute
> }
>
> Naturally, if some_attribute is nil, the comparison failed (since nil is
> not comparable). I am looking for something like this:
>
> my_array.sort {
> |x,y| x.some_attribute <=> y.some_attribute unless
> (x.some_attribute.nil? or y.some_attribute.nil?)
> }
>
> which I have tried without having success (Error was: comparison of
> MyClass with MyClass failed).

You have to return something from the comparison. Try something like:

my_array.sort { |x,y|
x1 = x.some_attribute
y1 = y.some_attribute
if (not x1.nil?) and (not y1.nil?)
x1 <=> y1
elsif x1.nil? and y1.nil?
0
elsif x1.nil?
-1
else
1
end
}


carp __

3/8/2007 4:09:00 PM

0

Thank you Brian, the solution you offered solved my problems!

--
Posted via http://www.ruby-....

Gavin Kistner

3/9/2007 12:45:00 AM

0

On Mar 8, 5:52 am, "Farrel Lifson" <farrel.lif...@gmail.com> wrote:
> Define <=> on your class:
>
> class MyClass
> def <=>(other)
> if @some_attribute.nil?
> return -1
> elsif @other.some_attribute.nil?
> return 1
> else
> @some_attribute <=> other.some_attribute
> end
> end
> end

I find your style of mixing imperative and functional return
parameters odd. I would have expected either:

if foo
-1
elsif bar
1
else
x <=> y
end

OR

if foo
return -1
elsif bar
return 1
else
return x <=> y
end

but not the combination you have above. FWIW, I favor the former
style, as it's just a hair faster.