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/
如果你正在寻找类似阵列的东西,请看一下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 个解决方案
#1
3
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 []
)
如果这样的定义太混乱,那么可以用不同的方式命名方法(例如#path而不是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
#2
1
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
如果你真的想要这样的东西,那么Ruby允许你在你选择的类上实现[]和[] =的自定义版本,包括语言提供的Hash类。如果修改基类,请小心使用
#1
3
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 []
)
如果这样的定义太混乱,那么可以用不同的方式命名方法(例如#path而不是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
#2
1
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
如果你真的想要这样的东西,那么Ruby允许你在你选择的类上实现[]和[] =的自定义版本,包括语言提供的Hash类。如果修改基类,请小心使用