如何对范围数组进行排序
ranges = [Range.new(0, 3, true), Range.new(3, 5, true), Range.new(5, 7, true), Range.new(7, 9, true), Range.new(9, 11, true), Range.new(11, 100, true)]
ranges.sort
=> ArgumentError: comparison of Range with Range failed
from (irb):7:in `sort'
from (irb):7
from /Users/praveena/.rvm/rubies/ruby-2.0.0-p247/bin/irb:16:in `<main>'
但是当我尝试
时2.0.0p247 :022 > (3...4) <=> (4...8)
=> nil
2.0.0p247 :023 > (3...4) <=> (1...2)
=> nil
我错过了什么吗?
答案 0 :(得分:2)
nil
不是用于排序的比较操作的可用值。
如果您在两个<=>
个对象Comparable
之间尝试a <=> b
,它们将始终返回-1,0或1表示“a小于b”,“a等于b”,并且“大于b”。
因此,要对Range
个对象进行排序,您需要覆盖<=>
并定义自己应该排序的顺序。注意,这必须是您为了对它们进行排序而编写的内容。 ,Range
个对象没有固有的或有意义的排序顺序。
例如,我可以决定范围按照Range
的开头顺序排序,如果它们相等则会回落到Range
的结尾:
class Range
def <=>(other)
[min, max] <=> [other.min, other.max]
end
end
[(1..3),(1...3),(4..5),(2..3)].sort
=> [1...3, 1..3, 2..3, 4..5]
答案 1 :(得分:2)
似乎范围有<=>
的实现,但不完整。让我们检查:
> Range.new(3,4) <=> Range.new(3,4)
=> 0
# It seems that it correctly identify when the two are equals
> Range.new(3,4) <=> Range.new(4,4)
=> nil
# But it seems that it fails to fail when both are different!
此方法在Range
中定义,因为它实际上是on the Object
class(!!!)定义的,因此每个对象都定义了此方法,这并不意味着它可以工作。实际上,范围的实现是默认的。让我们检查一下:
# lets define a dummy class
class A
end
=> nil
# and create an object
a = A.new
=> #<A:0x9b1d998>
# can correctly identify when equal
a <=> a
=> 0
# but invalid answer when not equal!
a <=> 1
=> nil
此时,您现在应该了解代码中发生了什么。
范围完全可以理解,范围没有规范的<=>
方法,因为没有更大范围的数学定义(我知道),也不是常识定义。