如何处理组合[] + =用于在Ruby中自动生成散列? [英] How to handle combination []+= for auto-vivifying hash in Ruby?

查看:151
本文介绍了如何处理组合[] + =用于在Ruby中自动生成散列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  class AutoHash<哈希
def初始化(* args)
super()
@update,@update_index = args [0] [:update],args [0] [:update_key]除非
args.empty?
结束

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

def [] =(k,v)
@update [@update_index ] = self如果@update和@update_index
super
end

def few(n = 0)
Array.new(n){AutoHash.new}
end
end

该类允许执行以下操作

  a = AutoHash.new 
a [:a] [:b] = 1
pa [:c]#=> ; {}#键:c尚未创建
p a#=> {:a => {:b => 1}}#注意,它没有键:c

a,b,c = AutoHash.new.few 3
b [ :d] = 1
p [a,b,c]#=> [{},{:d => 1},{}]#散列是独立的

更高级的定义这个类,这对我来说有点难理解。

问题

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

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

您会如何处理?是否可以定义 [] + = 运算符?






相关问题



  1. 在Ruby中使用新运算符对自动生成散列进行多重初始化
    红宝石散列初始化r
    仍然打开:
    如何创建深层复制操作符/在Ruby中克隆对象?


在Ruby中使用 [] + = 方法。当你输入

  x [y] + = z 



  x [y] = x [y] + z 

所以 [] 和<在 x (并且 + >)上调用code> [] = 调用 x [y] ,在这种情况下,它是 AutoHash )。我认为处理这个问题的最好方法是在 AutoHash 上定义一个 + 方法,它会返回这是争论。这将使 AutoHash.new [:x] + = y 几乎适用于任何类型的 y ,因为 y.class '为字符串, 0 为数字,...)加 y 几乎总是等于 y

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

添加该方法将使这两个工作成为可能:

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

#字符串:
a = AutoHash.new
5.times {a [:sum] + ='a string'}
a [:sum]#= > 一个字符串一个字符串一个字符串一个字符串一个字符串

顺便说一下,这里是一个清洁工您的代码版本:

  class AutoHash<哈希
def初始化(args = {})
super
@update,@update_index = args [:update],args [:update_key]
结束

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

def [] =(k,v)
@update [@update_index] = self如果@update和@update_index
超级
结束

def +(x); X; end
$ b $ def self.few(n)
Array.new(n){AutoHash.new}
end
end

:)


In order to implement auto-vivification of Ruby hash, one can employ the following class

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

This class allows to do the following things

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

There is a bit more advanced definition of this class proposed by Joshua, which is a bit hard for me to understand.

Problem

There is one situation, where I think the new class can be improved. The following code fails with the error message NoMethodError: undefined method '+' for {}:AutoHash

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

What would you do to handle it? Can one define []+= operator?


Related questions

  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. still open: How to create an operator for deep copy/cloning of objects in Ruby?

解决方案

There is no way to define a []+= method in ruby. What happens when you type

x[y] += z

is

x[y] = x[y] + z

so both the [] and []= methods are called on x (and + is called on x[y], which in this case is an AutoHash). I think that the best way to handle this problem would be to define a + method on AutoHash, which will just return it's argument. This will make AutoHash.new[:x] += y work for just about any type of y, because the "empty" version of y.class ('' for strings, 0 for numbers, ...) plus y will almost always equal y.

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

Adding that method will make both of these work:

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

And by the way, here is a cleaner version of your code:

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中自动生成散列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆