Как изменить Hash, чтобы разрешить доступ к элементу 'hash [: a] [: b]' по более короткому 'hash [: a,: b]' в Ruby? - PullRequest
1 голос
/ 08 июля 2010

Я был бы рад получить доступ к любому элементу многомерного хеш-массива с помощью более короткого выражения

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 ]

3 голосов
/ 08 июля 2010

Я исправил свой код, и теперь он работает

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 голос
/ 08 июля 2010

Если вы действительно хотите что-то подобное, Ruby позволяет вам реализовывать пользовательские версии [] и []= для классов по вашему выбору, включая класс Hash, предоставляемый языком.Используйте с осторожностью при изменении базовых классов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...