I would be happy to access any 开发者_如何学运维element of multi-dimensional hash-array by a shorter expression
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}}
I realize that in this way one eliminates the possibility to have a hash key being an array.
{[:a,:b] => "c"}
Since it is quite rare situation, I would prefer to reduce number of [] in my expressions.
How can one achieve this?
Update
Ok, I wasn't clear. The problem is that I have tried to make custom [] and []= methods myself, but failed. Could you show me how such functionality can be implemented?
Multi-dimensional arrays
If you are looking for something similar for arrays, have a look on 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 ] ]
I have fixed my code, so now it works
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
Examples
a = AutoHash.new
a[:a][:b][:c] = 123
a[:a,:b,:c] = 321
p a # => {:a=>{:b=>{:c=>321}}}
If such definition is too confusing, then one could name the method differently (e.g. #path instead of redifining [])
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
If you really want something like this then Ruby allows you to implement custom versions of [] and []= on classes of your choice including the Hash class provided by the language. Use with care if modifying base classes
 
         
                                         
                                         
                                         
                                        ![Interactive visualization of a graph in python [closed]](https://www.devze.com/res/2023/04-10/09/92d32fe8c0d22fb96bd6f6e8b7d1f457.gif) 
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论