如何在Ruby中创建一个比较字符串的哈希,忽略大小写?

Col*_*len 17 ruby hash key

在Ruby中,我想将一些东西存储在Hash中,但我不希望它区分大小写.例如:

h = Hash.new
h["HELLO"] = 7
puts h["hello"]
Run Code Online (Sandbox Code Playgroud)

这应该输出7,即使情况不同.我可以覆盖哈希的相等方法或类似的东西吗?

谢谢.

Rya*_*ary 16

如果你真的想忽略两个方向的情况下,并处理所有的哈希方法,如#has_key?,#fetch,#values_at,#delete,等你,如果你想从头开始构建这个需要做一些工作,但如果你创建一个扩展的新类从类ActiveSupport :: HashWithIndifferentAccess,你应该能够很容易地这样做:

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
Run Code Online (Sandbox Code Playgroud)

这是一些示例行为:

h = CaseInsensitiveHash.new
h["HELLO"] = 7
h.fetch("HELLO")                # => 7
h.fetch("hello")                # => 7
h["HELLO"]                      # => 7
h["hello"]                      # => 7
h.has_key?("hello")             # => true
h.values_at("hello", "HELLO")   # => [7, 7]
h.delete("hello")               # => 7
h["HELLO"]                      # => nil
Run Code Online (Sandbox Code Playgroud)

  • 警告,此方法不适用于嵌套哈希,因为不会使用您的子类 (3认同)

Myr*_*rys 16

为了防止此更改完全破坏程序的独立部分(例如您正在使用的其他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
Run Code Online (Sandbox Code Playgroud)

在覆盖赋值和检索功能之后,它几乎是蛋糕.创建Hash的完全替换需要更加细致地处理完整实现所需的别名和其他函数(例如,#has_key?和#store).上面的模式可以很容易地扩展到所有这些相关的方法.

  • 我意识到这已经差不多五年了,但是"你不敏感的土块"让我大笑起来.布拉沃. (5认同)