代码之家  ›  专栏  ›  技术社区  ›  Andy

如何在Ruby中处理组合[]+=来自动激活hash?

  •  1
  • Andy  · 技术社区  · 14 年前

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

    a bit more advanced definition 这个班的 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?
    3 回复  |  直到 7 年前
        1
  •  5
  •   Adrian    14 年前

    无法定义 []+= 方法。当你打字时会发生什么

    x[y] += z
    

    x[y] = x[y] + z
    

    所以 [] []= 方法被调用 x (和 + 正在调用 x[y] ,在本例中是 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
    

    :)

        2
  •  1
  •   Damien Justin Å utevski    9 年前

    我想你想要的是:

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

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

    它将返回3,然后返回6,等等,没有错误,因为新值的默认值是0。

        3
  •  0
  •   Brian K    11 年前
    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 }