if i make an object sortable using <=> as so:
def <=> anItem
@date <=> anItem.date
end
and date is nil, it fails. What's the right way to handle nils in this
scenario?
thanks.
if i make an object sortable using <=> as so:
def <=> anItem
@date <=> anItem.date
end
and date is nil, it fails. What's the right way to handle nils in this
scenario?
thanks.
def <=> anItem
@date.nil? ? -1 : @date <=> anItem.date
end
You can set the -1, to 0, or 1 depdending where you want the objects
with nil @dates placed.
Farrel
On 3/9/06, larry <ljw1001@gmail.com> wrote:
if i make an object sortable using <=> as so:
def <=> anItem
@date <=> anItem.date
endand date is nil, it fails. What's the right way to handle nils in this
scenario?thanks.
Actually you can shorten it a bit further if you use
@date ? @date <=> anItem.date : -1
That's due to the fact that in Ruby nil is equivalent to false in
conditional expression.
Farrel
On 3/9/06, Farrel Lifson <farrel.lifson@gmail.com> wrote:
def <=> anItem
@date.nil? ? -1 : @date <=> anItem.date
endYou can set the -1, to 0, or 1 depdending where you want the objects
with nil @dates placed.Farrel
On 3/9/06, larry <ljw1001@gmail.com> wrote:
> if i make an object sortable using <=> as so:
>
> def <=> anItem
> @date <=> anItem.date
> end
>
> and date is nil, it fails. What's the right way to handle nils in this
> scenario?
>
> thanks.
>
>
>
Farrel Lifson wrote:
Actually you can shorten it a bit further if you use
@date ? @date <=> anItem.date : -1
That's due to the fact that in Ruby nil is equivalent to false in
conditional expression.
Speaking of this very topic, I am having an issue where I want to sort
objects by two of its attributes in a SortedSet, but its not working
out:
I'd like it to be sorted first by its :a attribute, but if they are
equal, by whatever sorting on the :b attributes comes up with. Anybody
know what I'm doing wrong in this test code? The third and fourth
elements are not in the proper order (excuse the overly verbose <=>
method... I was trying to get it working).
<snip>
puma:~> cat settest
#!/usr/bin/env ruby
X = Struct.new :a, :b
class X
def <=> other
if not @a
1
elsif not @b
-1
else
if @a == other.a
@b <=> other.b
else
@a <=> other.a
end
end
end
end
require 'set'
s = SortedSet.new
s << X.new( 1, 2)
s << X.new( 2, 1)
s << X.new( 3, 3)
s << X.new( 3, 4)
s << X.new( 1, 2)
p s
x = X.new 3, 3
y = X.new 3, 4
p x <=> y
p y <=> x
p x <=> x
puma:~> ./settest
#<SortedSet: {#<struct X a=1, b=2>, #<struct X a=2, b=1>, #<struct X
a=3, b=4>, #<struct X a=3, b=3>}>
1
1
1
puma:~>
</snip>
Actually, the weird thing is that the dates were never nil, but the
sort thinks they are. Adding the required nil checking code suppressed
the exception but the sort is returning things in random order because
it sees each date as nil.
I posted a followup on the rails list because I thought it might be a
rails issue. They suggested I use an explicit sort block instead:
@assignments= @assignments.sort {|a,b| a.date <=> b.date}
and it works. Not sure why.
as a quick alternative, sorting by several attributes is pretty easy
using #sort_by
X = Struct.new :a, :b
s =
s << X.new(3, 3)
s << X.new(3, 4)
s << X.new(1, 2)
s << X.new(4, 8)
s << X.new(4, 2)
sorted = s.sort_by { |a| [a.a,a.b] }
sorted.each { |v| p v }
#<struct X a=1, b=2>
#<struct X a=3, b=3>
#<struct X a=3, b=4>
#<struct X a=4, b=2>
#<struct X a=4, b=8>
Cameron
On 3/9/06, Toby DiPasquale <toby@cbcg.net> wrote:
Speaking of this very topic, I am having an issue where I want to sort
objects by two of its attributes in a SortedSet, but its not working
out:I'd like it to be sorted first by its :a attribute, but if they are
equal, by whatever sorting on the :b attributes comes up with.
I don't think you can access the attributes of a Struct from inside it
using object variables (like @a).
C:\Documents and Settings\flifson\Desktop>irb
irb(main):001:0> X = Struct.new :a,:b
=> X
irb(main):002:0> class X
irb(main):003:1> def print_attributes
irb(main):004:2> puts "#{@a}:#{b}"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> s = X.new 'hello','world'
=> #<struct X a="hello", b="world">
irb(main):008:0> s.print_attributes
:world
Notice only the value of the b attribute was printed ('world').
That's because self. was implicitly added to the front of it, so it
became self.b which will return the correct value. Changing it to:
def <=> other
if not a
1
elsif not b
-1
else
if a == other.a
b <=> other.b
else
a <=> other.a
end
end
end
produces:
C:\Documents and Settings\flifson>ruby settest.rb
#<SortedSet: {#<struct X a=1, b=2>, #<struct X a=2, b=1>, #<struct X a=3, b=3>,
#<struct X a=3, b=4>}>
-1
1
0
My guess is that the Struct is really a type of Hash and that it uses
the method_missing system hook to actually retrieve the data from
whatever it uses to store the data. It has a lot of Hash like methods
such as values, each_pair etc etc.
Farrel