如何处理组合[] + =在Ruby中自动生成哈希?

And*_*rei 1 ruby hash autovivification operator-keyword

为了实现Ruby哈希的自动生成,可以使用以下类

class AutoHash < Hash
  def initialize(*args)
    super()
    @update, @update_index = args[0][:update], args[0][:update_key] unless 
args.empty?
  end

  def [](k)
    if self.has_key?k
      super(k)
    else
      AutoHash.new(:update => self, :update_key => k)
    end
  end

  def []=(k, v)
    @update[@update_index] = self if @update and @update_index
    super
  end

  def few(n=0)
    Array.new(n) { AutoHash.new }
  end
end
Run Code Online (Sandbox Code Playgroud)

该类允许执行以下操作

a = AutoHash.new
a[:a][:b] = 1
p a[:c] # => {}             # key :c has not been created
p a     # => {:a=>{:b=>1}}  # note, that it does not have key :c

a,b,c = AutoHash.new.few 3
b[:d] = 1
p [a,b,c] # => [{}, {:d=>1}, {}]  # hashes are independent
Run Code Online (Sandbox Code Playgroud)

还有更多的先进定义这个类的由约书亚提出的,这是一个有点硬,我听不懂.

问题

有一种情况,我认为新课程可以改进.以下代码失败并显示错误消息NoMethodError: undefined method '+' for {}:AutoHash

a = AutoHash.new
5.times { a[:sum] += 10 }
Run Code Online (Sandbox Code Playgroud)

你会做什么来处理它?可以定义[]+=运营商吗?


相关问题

  1. 是否可以在Ruby中自动初始化多维哈希数组,就像在PHP中一样?
  2. 使用Ruby ruby​​哈希初始化r中的新运算符对自动生成哈希进行多次初始化
  3. 仍然开放: 如何在Ruby中创建一个深层复制/克隆对象的运算符?

Adr*_*ian 5

无法[]+=在ruby中定义方法.键入时会发生什么

x[y] += z
Run Code Online (Sandbox Code Playgroud)

x[y] = x[y] + z
Run Code Online (Sandbox Code Playgroud)

所以无论是[][]=方法被称为上x(和+被称为上x[y],在这种情况下是一个AutoHash).我认为处理这个问题的最好方法是定义一个+方法AutoHash,它将返回它的参数.这将AutoHash.new[:x] += y适用于几乎任何类型的y,因为y.class(''对于字符串,0数字,...)加上的"空"版本y几乎总是相等y.

class AutoHash
  def +(x); x; end
end
Run Code Online (Sandbox Code Playgroud)

添加该方法将使这两个工作:

# Numbers:
a = AutoHash.new
5.times { a[:sum] += 10 }
a[:sum] #=> 50

# Strings:
a = AutoHash.new
5.times { a[:sum] += 'a string ' }
a[:sum] #=> "a string a string a string a string a string "
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这是一个更简洁的代码版本:

class AutoHash < Hash
  def initialize(args={})
    super
    @update, @update_index = args[:update], args[:update_key]
  end

  def [](k)
    if has_key? k
      super(k)
    else
      AutoHash.new :update => self, :update_key => k
    end
  end

  def []=(k, v)
    @update[@update_index] = self if @update and @update_index
    super
  end

  def +(x); x; end

  def self.few(n)
    Array.new(n) { AutoHash.new }
  end
end
Run Code Online (Sandbox Code Playgroud)

:)