如何在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

在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"=>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}