如何有用的是Object#<=>为nil
?我认为这只受到人们的想象力的限制。
实施例#1
下面是如何可以是有用的行人的例子。假设你想对数组进行排序:
arr = [1,nil,3,nil,2]
所有的nil
来临了第一,所以它会返回:
[nil, nil, 1, 2, 3]
由于:
nil<=>nil #=> 0
,并为所有非nil
物体a
:
nil<=>x #=> nil
x<=>nil #=> nil
,我们可以这样写:
arr.sort { |a,b| (a<=>b) ? a<=>b : a.nil? ? -1 : 1 }
#=> [nil, nil, 1, 2, 3]
例2
现在让我们来看看这是更有趣的第二个例子。假设我们有超卖门票的戏剧表演,必须拒绝一些顾客,并给他们退款。哈希tickets
显示了他们的票付出什么每个人:
ticket_holders = { 'bob'=>10, 'lucy'=>15, 'cher'=>5, 'arnold'=>12 }
我们希望最小化发行的退款,但不希望从转身离开名人的负面宣传,由下式给出:
celebrities = ['arnold', 'cher']
所以我们会给他们最高的偏好。因此,我们希望按降序对ticket_holders
进行排序,除了我们希望键为celebrities
之前的键值对。也就是说,我们希望得到的结果是:
['cher', 'arnold', 'lucy', 'bob']
或
['arnold', 'cher', 'lucy', 'bob']
我们去一个通用的解决方案:
module Enumerable
def sort_by_nils_first
sort do |a,b|
av = yield(a)
bv = yield(b)
(av<=>bv) ? av<=>bv : av.nil? ? -1 : 1
end
end
end
我们因此适用:
ticket_holders.sort_by_nils_first { |name,price|
celebrities.include?(name) ? nil : -price }.map(&:first)
#=> ["arnold", "cher", "lucy", "bob"]
仅考虑celebriti的数量在这个世界上,以及如何对待他们,我认为这是一个非常有用的方法。
应用到前面的例子中,我们得到:
[1,nil,3,nil,2].sort_by_nils_first(&:itself)
#=> [nil, nil, 1, 2, 3]
,我已经使用从V2.2 Object#itself。
sort_by_nils_first
当然可以修改为当没有给出块时返回Enumerator
,以使其与Enumerable#sort_by相当。
那么解释行为。在你看来,有没有一种情况是有用的?或者,这仅仅是任何语言的陷阱之一? – kdbanman 2015-03-08 20:02:47
我认为这是微不足道的;它的存在使得如果你对于事情的表现应该有不同的意见,那么你可以实现这些意见,但我同意在大多数情况下它通常没有用。 – 2015-03-08 20:05:12