1

为了实现 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

此类允许执行以下操作

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

Joshua对这个类提出了一个更高级的定义,这对我来说有点难以理解。

问题

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

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

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


相关问题

  1. 在 Ruby 中是否可以像在 PHP 中那样自动初始化多维哈希数组?
  2. 使用 Ruby 中的新运算符对自动激活哈希进行多次初始化 Ruby 哈希初始化 r
  3. 仍然开放: 如何在 Ruby 中创建用于深度复制/克隆对象的运算符?
4

3 回答 3

5

没有办法[]+=在 ruby​​ 中定义方法。键入时会发生什么

x[y] += z

x[y] = x[y] + z

所以 the[][]=方法都被调用x(并且+被调用 on x[y],在这种情况下是 an AutoHash)。我认为处理这个问题的最好方法是定义一个+方法 on AutoHash,它只会返回它的参数。这AutoHash.new[:x] += y几乎适用于任何类型的y,因为y.class(''对于字符串,0对于数字,...) plus的“空”版本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

:)

于 2010-07-03T19:05:28.043 回答
1

我想你想要的是这样的:

hash = Hash.new { |h, k| h[k] = 0 }

hash['foo'] += 3 # => 3

这将返回 3,然后是 6,以此类推,没有错误,因为新值默认分配为 0。

于 2015-02-05T01:05:55.803 回答
0
require 'xkeys' # on rubygems.org

a = {}.extend XKeys::Hash
a[:a, :b] = 1
p a[:c] # => nil (key :c has not been created)
p a # => { :a => { :b => 1 } }

a.clear
5.times { a[:sum, :else => 0] += 10 }
p a # => { :sum => 50 }
于 2013-07-26T02:01:44.097 回答