2015-06-08 59 views
2

我有一个的默认值为0的哈希:Hash.new(0)散列值'floor'的值?

假设一个整数值,是有办法来设置一个“地板”,这样,如果数值超出地板下方,则返回地面?

例如:

h = Hash.new(0) 
h.floor = 0 

h[:five] += 5 
h[:five] 
#=> 5 

h[:negative_five] -= 5 
h[:negative_five] 
#=> 0 
+0

如果地板被退回或钥匙的值永远不会低于地板(即h [:negative_five] + 8等于3或等于8)? – floum

+0

在这种情况下,它可能只是返回的值,所以'h [:negative_five] + 8 == 8'但这是一个非常好的点 – dax

+1

我认为这是一个坏主意。假设@Thomas的解决方案,这里是一个例子。假设'h = {a:-1}; m = MyHash.new; m [:b] = -2; m.floor = 0; hm = h.merge(m)#=> {:a => - 1,:b => - 2}; mh = m.merge(h)#=> {:b => - 2,:a => - 1}; hm == mh#=> true'。然后'hm.class#=> Hash; hm [:b]#=> -2'和'mh.class#=> MyHash; mh [:b]#=> ArgumentError'。为什么是例外?因为我们没有设置'mh.floor = 0'。使用简单的方法会不会更容易和更少问题:'def max_of_value_and_floor(h,k,floor); (h [k]

回答

7

这里是一个可能的实现

class MyHash < Hash 
    attr_writer :floor 

    def [](key) 
     # you can use one of those two lines or your own code in case the floor hasn't been define 
     # raise 'floor value must be defined' if @floor.nil? 
     # super key if @floor.nil? 
     value = (fetch(key) < @floor ? @floor : fetch(key)) 
    end 
end 
+3

,而不是手动定义'floor ='方法,可以使用'attr_writer:floor'。 –

+1

[fetch(key),@floor] .max也可以工作 –

+0

这也不错,谢谢你的回答 – dax

0

现在我使用的是这样的:

def enforce_floor!(hash, floor) 
    hash.each do |key, value| 
    hash[key] = floor if value < floor 
    end 
end 

它的工作原理,但我想,也许有更优雅的解决方案

2

这里是一个新的实现,反映了你不应该存储地板上的任何值如下:

class FlooredHash < Hash 
    attr_writer :floor 

    def floor 
    @floor || -(2 ** 32) # setting the default floor for all FlooredHashes 
    end 

    def []=(key, value) 
    super(key, [value, floor].max) 
    end 
end 

要知道,你将不得不如果需要重新定义#store为好。

+0

这是一个不错的解决方案,非常感谢 – dax

+0

,非常欢迎。 – floum