2

我目前有一个可以使用 +=1 为自身增值的哈希

@hash = Hash.new { |hash, key| hash[key] = Hash.new(0) }
@hash[string1][string2] += 1

这将返回一个看起来像这样的哈希:

@hash = {string1 => {string2 => 1 }}

每次迭代相同的字符串值时,该整数值都会增加一。

现在我需要向哈希添加另一个值,所以它看起来像这样......

@hash = {string1 => {string2 => {string3 => 1}}}

并以相同的方式增加该数字。

不幸的是这段代码:

@hash = Hash.new { |hash, key| hash[key] = Hash.new(0)}
@hash[string1][string2][string3] += 1

返回错误提示“无法将字符串转换为整数”。我有一种感觉,这是因为添加了一个元素,并且我有 Hash.new(0),所以它在我有一个字符串的地方期待一个整数。那是对的吗?

我将如何设置此哈希以便它可以处理额外的维度并且仍然在最后执行 += 1 以便值增加?

谢谢。

4

3 回答 3

2

本质上,你不能。您可以将 en 空键默认为新哈希,也可以将其默认为0,因此您必须选择更重要的内容并使用您自己的类行为处理其他情况。

在您的第一个示例中,您是从 开始string2 => 1并将其替换为string2 => { string3 => 1 },还是这两个单独的示例?

这个散列可以让你在任意深度查找和设置值,而不需要它们首先存在:

h = Hash.new {|hash, key| hash[key] = Hash.new(&hash.default_proc) }
h[1][2][3] = 4  #=> {1=>{2=>{3=>4}}}

更新

这是一个类包装器如何工作的示例(快速而肮脏,未经测试):

require 'forwardable'
class AutoHash
  extend Forwardable
  attr_reader :data

  def_delegators :@data, :[], :[]=

  def initialize
    @data = Hash.new {|hash, key| hash[key] = Hash.new(&hash.default_proc) }
  end

  def increment(*keys, value)
    current_hash = data
    keys[0..-2].each do |key|
      current_hash = current_hash[key]
    end
    current_hash[keys[-1]] = 0 unless current_hash.has_key?(keys[-1])
    current_hash[keys[-1]] += value
  end
end

a = AutoHash.new
a.increment(:string1, :string2, :string3, 2)
a.increment(:string1, :string2, :string3, 5)
a.increment(:string1, :string4, 10)

a.data # => {:string1=>{:string2=>{:string3=>7}, :string4=>10}} 
于 2013-06-21T19:50:27.163 回答
0

I don't think you can overload that. But you could derive another:

@hash2=Hash.new { |hash,key| hash[key] = @hash }

that should let you use @hash for 2 dimensions and @hash2 for 3 dimensions

If you need variable length, and a method call is acceptable, you could use something like

def deephash (*keys)
  return 0 if keys.length == 0
  key = keys.shift
  { key => deephash(*keys) }
end

n=deephash("a","b","c","d")
=> {"a"=>{"b"=>{"c"=>{"d"=>0}}}}

n["a"]["b"]["c"]["d"] += 1
=> 1

n
=> {"a"=>{"b"=>{"c"=>{"d"=>1}}}}
于 2013-06-21T19:53:44.493 回答
0
irb(main):001:0> h=Hash.new {|h,k| h[k]=Hash.new {|h,k| h[k]=Hash.new(0)}}
=> {}
irb(main):002:0> h[:a][:b][:c]+=1
=> 1
irb(main):003:0> h
=> {:a=>{:b=>{:c=>1}}}
于 2013-06-21T19:52:36.967 回答