我不喜欢为范围内的每个可能条目创建单独的键/值对的想法。它根本不可扩展,尤其是对于广泛的范围。考虑这个小范围:
'a' .. 'zz'
这将导致 702 个额外的密钥。尝试('a'..'zz').to_a
乐趣。前进。我会等。
拦截查找,而不是创建密钥。重用RangedHash
类名:
class RangedHash < Hash
def [](key)
return self.fetch(key) if self.key? key
self.keys.select{ |k| k.is_a? Range }.each do |r_k|
return self.fetch(r_k) if r_k === key
end
nil
end
end
foo = RangedHash.new
foo[1] = [6,2,2]
foo[2] = [7,4,5]
foo[3..7] = [7,2,1]
此时foo
看起来像:
{1=>[6, 2, 2], 2=>[7, 4, 5], 3..7=>[7, 2, 1]}
测试方法:
require 'pp'
3.upto(7) do |i|
pp foo[i]
end
哪个输出:
[7, 2, 1]
[7, 2, 1]
[7, 2, 1]
[7, 2, 1]
[7, 2, 1]
对于范围内的任何值,这将输出与该范围关联的值。超出范围但仍定义在散列中的值正常工作,返回nil
散列中不存在的键也是如此。并且,它使散列尽可能小。
不利的一面是,或任何问题的解决方案是范围内的键可能重叠,从而导致冲突。在大多数提议的解决方案中,键会相互踩踏,这将/可能最终返回错误的值。此方法不会这样做,因为覆盖范围键需要直接冲突。
要解决此问题,需要确定是否允许重叠,如果允许,是否可以返回找到的第一个重叠,或者是否存在确定“最佳拟合”的逻辑,即适合的最小范围,或者一些完全其他标准。或者,如果值相同,是否应该加入重叠以形成更大的范围?这是一罐蠕虫。