为什么在对Ruby中的对象中包含的浮点数进行排序时会出现ArgumentError?

时间:2014-03-23 20:25:39

标签: ruby sorting floating-point

我可以对浮动列表进行排序,没问题。但是,如果我试图比较一个对象中的浮点数来对列表中的对象进行排序,我会收到此错误:

`sort': comparison of HateRuby with HateRuby failed (ArgumentError)

以下是一些代码:

class HateRuby
    attr_reader :aFloat
    attr_writer :aFloat

    def initialize(f)
        @aFloat = f
    end
end

puts "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}\n\n"

x = []
x << HateRuby.new(3.3)
x << HateRuby.new(2.2)
x << HateRuby.new(1.1)

puts "x contents:"
x.each { |f| puts "#{'%.2f' % f.aFloat}: #{f.aFloat.class}" }

x.sort { |a,b| a.aFloat <=> b.aFloat }

y = x.sort

puts "y contents:"
y.each { |f| puts "#{'%.2f' % f.aFloat}: #{f.aFloat.class}" }

这会产生:

[path]/Ruby/rb3D54.tmp:21:in `sort': comparison of HateRuby with HateRuby failed (ArgumentError)
    from [path]/Ruby/rb3D54.tmp:21:in `<main>'
1.9.3-p125

x contents:
3.30: Float
2.20: Float
1.10: Float
Complete(1)

我当然不讨厌Ruby,但我很生气......

感谢任何人的倾听。

3 个答案:

答案 0 :(得分:0)

y = x.sort导致错误,因为#sort使用方法<=>比较对象。但是你没有定义方法。您的班级HateRuby#<=>中没有HateRuby方法。

虽然您要编写collection_object.sort,但提供了一个隐式块,例如collection_object.sort { |a,b| a <=> b }。这种方式正在进行排序。

现在看到它正在运作:

class HateRuby
    attr_reader :aFloat
    attr_writer :aFloat

    def initialize(f)
        @aFloat = f
    end
    def <=>(ob)
      # just for clarity I use `self`, you can remove it. as it is implicit.
      self.aFloat <=> ob.aFloat 
    end
end

x = []
x << HateRuby.new(3.3)
x << HateRuby.new(2.2)
x << HateRuby.new(1.1)
x.sort
# => [#<HateRuby:0x9e73d2c @aFloat=1.1>,
#     #<HateRuby:0x9e73d40 @aFloat=2.2>,
#     #<HateRuby:0x9e73d54 @aFloat=3.3>]

答案 1 :(得分:0)

您必须从Mixin <=>

实施方法Comparable
include Comparable

def <=> (other)

答案 2 :(得分:0)

你非常接近。 sort方法不对数组本身进行排序,它提供排序副本。你必须为它分配一个变量。这是你的代码改变了一行,一行消失了:

class HateRuby
    attr_reader :aFloat
    attr_writer :aFloat

    def initialize(f)
        @aFloat = f
    end
end

puts "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}\n\n"

x = []
x << HateRuby.new(3.3)
x << HateRuby.new(2.2)
x << HateRuby.new(1.1)

puts "x contents:"
x.each { |f| puts "#{'%.2f' % f.aFloat}: #{f.aFloat.class}" }

y = x.sort { |a,b| a.aFloat <=> b.aFloat } # <== This line changed
# y = x.sort                               # <== This line removed

puts "y contents:"
y.each { |f| puts "#{'%.2f' % f.aFloat}: #{f.aFloat.class}" }