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

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!

On 08/03/07, carp __ [email protected] wrote:

}
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

On Thu, Mar 08, 2007 at 10:42:44PM +0900, carp __ wrote:

|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
}

On Mar 8, 5:52 am, “Farrel L.” [email protected] wrote:

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.

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