您可以定义自己的继承自Hash 的类,并根据自己的喜好覆盖[](key) 方法。所以例如
class MyHash < Hash
def [](key)
# do something to return the appropriate value
end
end
根据您的调用代码所需的 Hash 接口的其他方法,您可能需要重写其他方法。
但是,鉴于您的用例,我怀疑您是否能够以非常有效的方式实现该方法,因为您必须遍历存储在哈希中的所有候选者(至少具有相同长度 +-1 的候选者)来评估它们是否匹配。当然,如果哈希中没有很多候选者,你可能会侥幸逃脱。
除此之外,我不认为在为哈希中的查找提供键时返回 1 的行为是非常类似于哈希的行为。我宁愿退回比赛。返回 1 将违反 IMO 最小意外原则。
OP评论后的补充
在不知道您的确切用例的情况下,也许我已经离开了,我会牺牲插入时间和空间的速度来提高查找时间的速度。这意味着我会在插入时预先计算一个键的所有变体,并将它们插入到用于存储的对象中。
class VariantsSet < Set
PLACEHOLDER = '_' # Use a character that will not be used in your keys
def add_variants(string)
merge(all_variants(string))
end
def delete(string)
all_variants(string).each { |variant| super(variant) }
end
def includes_any_variant?(string)
all_variants(string).any? { |variant| include?(variant) }
end
private
def all_variants(string)
downcase_string = string.downcase
string_length = string.length
variants = [downcase_string]
string_length.times do |i|
variants << downcase_string[0, i] + PLACEHOLDER + downcase_string[i + 1 , string_length]
end
variants
end
end
用法如下:
2.4.2 :026 > s = VariantsSet.new
=> #<VariantsSet: {}>
2.4.2 :027 > s.add_variants('foobar')
=> #<VariantsSet: {"foobar", "_oobar", "f_obar", "fo_bar", "foo_ar", "foob_r", "fooba_"}>
2.4.2 :028 > s.includes_any_variant?('foobaz')
=> true
2.4.2 :029 > s.includes_any_variant?('blubs')
=> false
根据您要存储的密钥数量,这可能需要相当多的 RAM,因此如果它失控,您可能不得不使用例如用于存储值的数据库。但我仍然建议预先计算变体。
如果您更喜欢的话,基本上可以使用 Hash 作为超类来完成相同的操作。
展开显示哈希实现
class VariantsHash < Hash
PLACEHOLDER = '_' # Use a character that will not be used in your keys
def []=(string, value)
all_variants(string).each do |variant|
super(variant, value)
end
end
def delete(string)
all_variants(string).each do |variant|
super(variant)
end
end
def [](string)
match = all_variants(string).detect do |variant|
super(variant)
end
super(match) if match
end
private
def all_variants(string)
downcase_string = string.downcase
string_length = string.length
variants = [downcase_string]
string_length.times do |i|
variants << downcase_string[0, i] + PLACEHOLDER + downcase_string[i + 1 , string_length]
end
variants
end
end