首页 > 解决方案 > Ruby 中的“只追加”/“只写”哈希

问题描述

我正在寻找一种“仅附加”哈希,其中键只能设置一次。

例如:

capitals = AppendOnlyHash.new
capitals['france'] = 'paris'
capitals['japan'] = 'tokyo'
capitals['france'] = 'nice' # raises immutable exception

任何图书馆建议或想法如何实现这一目标?

(用例是一个日志类型对象,它将被传递给许多松散连接的类,并希望检测是否有任何使用相同的键。)

标签: rubyhashmapruby-hashwriteonly

解决方案


有 10 种方法,直接改变哈希:

Hash.instance_methods.grep(/.+!\z/) << %i|[]= delete keep_if|
#⇒ [:select!, :filter!, :reject!, :compact!, delete, keep_if,
#   :transform_keys!, :transform_values!, :merge!, :[]=]

此外,有可能改变值本身capitals['france'] << ' and Lyon',),所以我们也要防止这种情况发生。

class MyHash < Hash; end

MyHash.prepend(
  Module.new do
    (Hash.instance_methods.grep(/.+!\z/) | %i|delete keep_if|).each do |method|
      define_method(method) do |*args|
        raise "Method #{method} is restricted since it is mutating"
      end
    end
    def []=(key, val)
      raise "This hash is immutable" if key?(key)
      super(key, val.freeze) # to prevent inplace mutations
    end
  end
)

需要从中派生,Hash否则我们将破坏所有哈希值。

我没有测试这段代码,但它应该可以开箱即用,(如果没有,这个想法应该很清楚。)


推荐阅读