【问题标题】:How to modify Hash to enable access of element 'hash[:a][:b]' by shorter 'hash[:a,:b]' in Ruby?如何在 Ruby 中通过更短的 'hash[:a,:b]' 修改 Hash 以启用对元素 'hash[:a][:b]' 的访问?
【发布时间】:2011-03-13 07:51:16
【问题描述】:

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

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 ] ]

【问题讨论】:

  • 我会使用所有需要的 []。否则,其他人会混淆查看您的代码的人。
  • 好的,我保证只为我自己保留这段代码,或者在我每次使用它时提供清晰的 cmets。 :)
  • @DanSingerman 我希望有 cmets 的赏金。是的。一千次是的。 @Andrei请不要为了(可以说)“更好”的查找而重新定义语言语法的这样一个基本方面。与您共事的任何人(几个月后您自己)只会被淘汰。
  • :) 我非常理解你的观点。不过别担心,除了这里,我不会给任何人看的。

标签: ruby arrays hash indexing


【解决方案1】:

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

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

【讨论】:

  • 有一点错别字:h.path(:a,:b:,:c)= 321 应该是 h.path(:a, :b, :c) = 321
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2011-08-18
    • 1970-01-01
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多