如何在Ruby中创建一个比较字符串的哈希,忽略大小写?
在Ruby中,我想在散列中存储一些东西,但我不希望它区分大小写。例如:如何在Ruby中创建一个比较字符串的哈希,忽略大小写?,ruby,hash,key,Ruby,Hash,Key,在Ruby中,我想在散列中存储一些东西,但我不希望它区分大小写。例如: h = Hash.new h["HELLO"] = 7 puts h["hello"] r = CaseInsensitiveHash['ASDF', 1, 'QWER', 2] => {"ASDF"=>1, "QWER"=>2} r['ASDF'] => nil ap r { "ASDF" => nil, "QWER" => nil } => {"ASDF"=&g
h = Hash.new
h["HELLO"] = 7
puts h["hello"]
r = CaseInsensitiveHash['ASDF', 1, 'QWER', 2]
=> {"ASDF"=>1, "QWER"=>2}
r['ASDF']
=> nil
ap r
{
"ASDF" => nil,
"QWER" => nil
}
=> {"ASDF"=>1, "QWER"=>2}
这应该是输出7,即使情况不同。我可以重写散列的相等方法或类似的方法吗
谢谢。有什么理由不只是使用string#upcase 如果坚持修改散列,可以执行以下操作
class Hash
alias :oldIndexer :[]
def [](val)
if val.respond_to? :upcase then oldIndexer(val.upcase) else oldIndexer(val) end
end
end
由于已启动,您还可以执行此操作以使设置不区分大小写:
class Hash
alias :oldSetter :[]=
def []=(key, value)
if key.respond_to? :upcase then oldSetter(key.upcase, value) else oldSetter(key, value) end
end
end
我还建议使用模块评估进行此操作。一般来说,我认为这是一个糟糕的计划;但是,如果我是您,我会创建一个hash子类来覆盖
[]
方法:
class SpecialHash < Hash
def [](search)
# Do special code here
end
end
class SpecialHash
要求“测试/单元”
类TestCaseInDifferenceThash
如果您真的想忽略两个方向的大小写并处理所有哈希方法,如#has#u key?
,#fetch
,#values_at
,#delete
等,如果您想从头开始构建它,您需要做一些工作,但如果您创建一个从类扩展的新类,你应该能够很容易地做到这一点,就像这样:
require "active_support/hash_with_indifferent_access"
class CaseInsensitiveHash < HashWithIndifferentAccess
# This method shouldn't need an override, but my tests say otherwise.
def [](key)
super convert_key(key)
end
protected
def convert_key(key)
key.respond_to?(:downcase) ? key.downcase : key
end
end
为了防止此更改完全破坏程序的独立部分(如您正在使用的其他ruby gems),请为不敏感哈希创建单独的类
class HashClod < Hash
def [](key)
super _insensitive(key)
end
def []=(key, value)
super _insensitive(key), value
end
# Keeping it DRY.
protected
def _insensitive(key)
key.respond_to?(:upcase) ? key.upcase : key
end
end
you_insensitive = HashClod.new
you_insensitive['clod'] = 1
puts you_insensitive['cLoD'] # => 1
you_insensitive['CLod'] = 5
puts you_insensitive['clod'] # => 5
类HashClod1
你感觉迟钝[冷]=5
使您不敏感['clod']35;=>5
在重写赋值和检索函数之后,它几乎就是蛋糕了。创建一个完整的散列替换将需要更加细致地处理别名和其他函数(例如,完整实现所需的#has#key?和#store)。上述模式可以很容易地扩展到所有这些相关方法。虽然Ryan McGeary的方法非常有效,而且几乎可以肯定是正确的方法,但有一个bug我无法识别其原因,它破坏了
散列[]
方法
例如:
h = Hash.new
h["HELLO"] = 7
puts h["hello"]
r = CaseInsensitiveHash['ASDF', 1, 'QWER', 2]
=> {"ASDF"=>1, "QWER"=>2}
r['ASDF']
=> nil
ap r
{
"ASDF" => nil,
"QWER" => nil
}
=> {"ASDF"=>1, "QWER"=>2}
虽然我还无法找到或修复该错误的根本原因,但以下黑客技术确实改善了问题:
r = CaseInsensitiveHash.new(Hash['ASDF', 1, 'QWER', 2])
=> {"asdf"=>1, "qwer"=>2}
r['ASDF']
=> 1
ap r
{
"asdf" => 1,
"qwer" => 2
}
=> {"asdf"=>1, "qwer"=>2}
只是想对这个答案再补充一点:覆盖#[]=在你收到的钥匙上打电话给#downcase,然后在#[]中你可以打电话给self.get(search.downcase)。@Federico Builes-+1-谢谢你的额外提示:-)太好了,我不知道!警告,此方法不适用于嵌套哈希,因为您的子类将不被使用假定正在使用所有CAP设置哈希。您可以轻松地将上述内容扩展到[]=作为后续内容,我真正需要的是忽略大小写/保留大小写的哈希,但子类化HashWithInferenceTaccess最终会占用原始键的大小写(更不用说上面的[]方法错误),所以我放弃了,改为在散列上用Monkey修补了一个fetch_漠不关心的方法。我意识到这是近五年前的事了,但“你这个麻木的家伙”让我大笑起来。太好了。警告:这对嵌套哈希也不起作用。@James就我所知,如果您将每个嵌套级别创建为HashClod,它会起作用。如果创建默认哈希,当然会失败。
r = CaseInsensitiveHash.new(Hash['ASDF', 1, 'QWER', 2])
=> {"asdf"=>1, "qwer"=>2}
r['ASDF']
=> 1
ap r
{
"asdf" => 1,
"qwer" => 2
}
=> {"asdf"=>1, "qwer"=>2}