Как заменить все значения в хэше новым значением? - PullRequest
3 голосов
/ 21 июня 2010

Допустим, у меня есть произвольно глубокий вложенный хэш h:

h = {
  :foo => { :bar => 1 },
  :baz => 10,
  :quux => { :swozz => {:muux => 1000}, :grimel => 200 }
  # ...
}

И скажем, у меня есть класс C, определенный как:

class C
  attr_accessor :dict
end

Как мнезаменить все вложенные значения в h, чтобы они теперь были C экземплярами с атрибутом dict, установленным на это значение?Например, в приведенном выше примере я ожидал бы что-то вроде:

h = {
  :foo => <C @dict={:bar => 1}>,
  :baz => 10,
  :quux => <C @dict={:swozz => <C @dict={:muux => 1000}>, :grimel => 200}>
  # ...
}

, где <C @dict = ...> представляет C экземпляр с @dict = ....(Обратите внимание, что как только вы достигнете значения, которое не является вложенным, вы перестанете заключать его в C экземпляров.)

Ответы [ 2 ]

1 голос
/ 21 июня 2010
class C
  attr_accessor :dict

  def initialize(dict)
    self.dict = dict
  end
end

class Object
  def convert_to_dict
    C.new(self)
  end
end

class Hash
  def convert_to_dict
    Hash[map {|k, v| [k, v.convert_to_dict] }]
  end
end

p h.convert_to_dict
# => {
# =>   :foo => {
# =>     :bar => #<C:0x13adc18 @dict=1>
# =>   },
# =>   :baz => #<C:0x13adba0 @dict=10>,
# =>   :quux => {
# =>     :swozz => {
# =>       :muux => #<C:0x13adac8 @dict=1000>
# =>     },
# =>     :grimel => #<C:0x13ada50 @dict=200>
# =>   }
# => }
1 голос
/ 21 июня 2010
def convert_hash(h)
  h.keys.each do |k|
    if h[k].is_a? Hash
      c = C.new
      c.dict = convert_hash(h[k])
      h[k] = c
    end
  end
  h
end

Если мы переопределим inspect в C, чтобы сделать вывод более дружелюбным, например:

def inspect
  "<C @dict=#{dict.inspect}>"
end

, а затем запустим ваш пример h, это даст:

puts convert_hash(h).inspect

{:baz=>10, :quux=><C @dict={:grimel=>200, 
 :swozz=><C @dict={:muux=>1000}>}>, :foo=><C @dict={:bar=>1}>}

Кроме того, если вы добавите метод initialize к C для установки dict:

def initialize(d=nil)
  self.dict = d
end

, тогда вы можете уменьшить 3 строки в середине convert_hash доh[k] = C.new(convert_hash_h[k])

...