如何修改Hash以通过Ruby中更短的'hash [:a,:b]'来访问元素'hash [:a] [:b]'?

时间:2010-07-08 12:35:18

标签: ruby arrays hash indexing

我很乐意通过更短的表达式访问多维哈希数组的任何元素

h = {a: {b: 'c'}}

# default way
p h[:a][:b] # => "c"

# a nicer way
p h[:a,:b] # => "c"

# nice assignment
h[:a,:b] = 1
p h # => {:a=>{:b=>1}}

我意识到以这种方式消除了将散列键作为数组的可能性。

{[:a,:b] => "c"}

由于情况非常罕见,我宁愿在表达式中减少[]的数量。

如何实现这一目标?


更新

好的,我不清楚。问题是我尝试自己制作自定义[][]=方法,但失败了。你能告诉我这样的功能是如何实现的吗?

多维数组

如果您正在寻找类似数组的内容,请查看narray gem http://narray.rubyforge.org/

>> a = NArray.int(5,5)
=> NArrayint5,5: 
[ [ 0, 0, 0, 0, 0 ], 
  [ 0, 0, 0, 0, 0 ], 
  [ 0, 0, 0, 0, 0 ], 
  [ 0, 0, 0, 0, 0 ], 
  [ 0, 0, 0, 0, 0 ] ]
>> a[1,2]
=> 0
>> a[1,2]=1
=> 1
>> a
=> NArrayint5,5: 
[ [ 0, 0, 0, 0, 0 ], 
  [ 0, 0, 0, 0, 0 ], 
  [ 0, 1, 0, 0, 0 ], 
  [ 0, 0, 0, 0, 0 ], 
  [ 0, 0, 0, 0, 0 ] ]
>> a[1,0..4]=1
=> 1
>> a
=> NArrayint5,5: 
[ [ 0, 1, 0, 0, 0 ], 
  [ 0, 1, 0, 0, 0 ], 
  [ 0, 1, 0, 0, 0 ], 
  [ 0, 1, 0, 0, 0 ], 
  [ 0, 1, 0, 0, 0 ] ]

2 个答案:

答案 0 :(得分:3)

我已经修复了我的代码,现在它可以正常工作

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

    def [] key,*args
      if args.count > 0
        self[key][*args]
      else
        if self.has_key? key
          super key
        else
          AutoHash.new :update => self, :update_key => key
        end
      end
    end

    def []= *args
      v = args.pop
      k = args.shift
      if args.count > 0
        self[k][*args]= v
      else
        @update[@update_index] = self if @update and @update_index
        super k,v
      end
    end
end

实施例

a = AutoHash.new
a[:a][:b][:c] = 123
a[:a,:b,:c] = 321
p a # => {:a=>{:b=>{:c=>321}}}

如果这样的定义过于混乱,那么可以用不同的方式命名方法(例如#path而不是重新定义[]

h[:a][:b][:c] = 123
p h.path(:a,:b,:c) # => 123

h.path(:a,:b,:c)= 321
p h #=> {:a=>{:b=>{:c=>321}}}

mypath = [:a,:b,:c]
p h.path(mypath) #=> 321

答案 1 :(得分:1)

如果你真的想要这样的东西,那么Ruby允许你在你选择的类上实现[][]=的自定义版本,包括语言提供的Hash类。如果修改基类

,请小心使用