Lo que quiero hacer es crear un objeto.que se inicializa con un hash y luego consulta este objeto para obtener valores de ese hash. Para aclarar las cosas aquí es un ejemplo aproximado de lo que quiero decir:
class HashHolder
def initialize(hash)
@hash = hash
end
def get_value(*args)
# What are my possibilities here?
end
end
holder = HashHolder.new({:a => { :b => { :c => "value" } } } )
holder.get_value(:a, :b, :c) # should return "value"
Sé que puedo realizar una iteración en la lista de argumentos como en:
def get_value(*args)
value = @hash
args.each do |k|
value = value[k]
end
return value
end
Pero si planeo usar mucho este método, esto va a degradar dramáticamente mi rendimiento cuando lo único que quiero hacer es acceder a un valor de hash.
¿Alguna sugerencia sobre eso?
Respuestas
7 para la respuesta № 1Para actualizar la respuesta ya que ha pasado un tiempo desde que se solicitó.
(probado en rubí 2.3.1)
Tienes un hash como este:
my_hash = {:a => { :b => { :c => "value" } } }
La pregunta formulada:
my_hash.get_value(:a, :b, :c) # should return "value"
Respuesta: Use "dig" en lugar de get_value, así:
my_hash.dig(:a,:b,:c) # returns "value"
Dado que el título de la pregunta es engañoso (debería ser algo así como: cómo obtener un valor dentro de un hash anidado con una matriz de claves), aquí hay una respuesta a la pregunta realmente formulada:
Obtención de valores hash ruby por una matriz de claves
Preparación:
my_hash = {:a => 1, :b => 3, :d => 6}
my_array = [:a,:d]
Responder:
my_hash.values_at(*my_array) #returns [1,6]
4 para la respuesta № 2
def get_value(*args)
args.inject(@hash, &:fetch)
end
En caso de que quiera evitar la iteración en la búsqueda (lo que no me parece necesario), entonces necesita aplanar el hash para almacenarlo:
class HashHolder
def initialize(hash)
while hash.values.any?{|v| v.kind_of?(Hash)}
hash.to_a.each{|k, v| if v.kind_of?(Hash); hash.delete(k).each{|kk, vv| hash[[*k, kk]] = vv} end}
end
@hash = hash
end
def get_value(*args)
@hash[args]
end
end
-3 para la respuesta № 3
Si sabe que la estructura del hash está siempre en ese formato, simplemente puede hacerlo:
holder[:a][:b][:c]
... devuelve "valor".