ruby - 如何处理 []+= 组合以在 Ruby 中自动激活散列?

标签 ruby hash operator-keyword autovivification

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

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

这个类允许做以下事情

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

a bit more advanced definition本类(class)的proposed by Joshua ,这对我来说有点难以理解。

问题

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

a = AutoHash.new
5.times { a[:sum] += 10 }

你会怎样处理它?可以定义 []+= 运算符吗?


相关问题

  1. Is auto-initialization of multi-dimensional hash array possible in Ruby, as it is in PHP?
  2. Multiple initialization of auto-vivifying hashes using a new operator in Ruby ruby hash initialization r
  3. 仍然开放: How to create an operator for deep copy/cloning of objects in Ruby?

最佳答案

无法在 ruby​​ 中定义 []+= 方法。当你输入时会发生什么

x[y] += z

x[y] = x[y] + z

因此 [][]= 方法都在 x 上调用(并且 + 被调用在 x[y] 上,在本例中是一个 AutoHash)。我认为处理这个问题的最好方法是在 AutoHash 上定义一个 + 方法,它只会返回它的参数。这将使 AutoHash.new[:x] += y 适用于任何类型的 y,因为 y.class< 的“空”版本('' 代表字符串,0 代表数字,...)加上 y 几乎总是等于 y.

class AutoHash
  def +(x); x; end
end

添加该方法将使这两种方法都起作用:

# 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 "

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

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

:)

关于ruby - 如何处理 []+= 组合以在 Ruby 中自动激活散列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3172342/

相关文章:

javascript - 如何在 ruby​​ 上实现时间序列、可缩放 Highcharts

ruby - 如何从 Ruby 中的哈希表中获取第一个键值对

c - 大文件的LZW编码

c - 关于左值的这五个陈述中哪一个是正确的?

ruby-on-rails - 使用具有连接条件的 Rails STI 模型

ruby-on-rails - 将两个数组与前置组合

jquery - 使用不同的 anchor 重新加载页面

java - 不带双引号的字符串追加

c - C 中的运算符优先级

arrays - Ruby:字符串在数组中显示为字符串