To, co zamierzam zrobić, to stworzyć obiektktóry jest inicjowany za pomocą skrótu, a następnie odpytuje ten obiekt, aby uzyskać wartości z tego skrótu. Aby to wyjaśnić, oto przybliżony przykład tego, co mam na myśli:
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"
Wiem, że mogę wykonać iterację na liście argumentów jak w:
def get_value(*args)
value = @hash
args.each do |k|
value = value[k]
end
return value
end
Ale jeśli planuję dużo korzystać z tej metody, dramatycznie obniży to moją wydajność, gdy wszystko, co chcę zrobić, to uzyskać dostęp do wartości skrótu.
Jakieś sugestie na ten temat?
Odpowiedzi:
7 dla odpowiedzi № 1Aby zaktualizować odpowiedź, ponieważ minęło już trochę czasu od momentu jej pytania.
(testowane w Ruby 2.3.1)
Masz taki skrót:
my_hash = {:a => { :b => { :c => "value" } } }
Pytanie zadane:
my_hash.get_value(:a, :b, :c) # should return "value"
Odpowiedź: Użyj „dig” zamiast get_value, na przykład:
my_hash.dig(:a,:b,:c) # returns "value"
Ponieważ tytuł pytania wprowadza w błąd (powinno to być coś w rodzaju: jak uzyskać wartość w zagnieżdżonym haszu za pomocą tablicy kluczy), oto odpowiedź na pytanie, które faktycznie zostało zadane:
Uzyskiwanie wartości skrótu ruby za pomocą tablicy kluczy
Przygotowanie:
my_hash = {:a => 1, :b => 3, :d => 6}
my_array = [:a,:d]
Odpowiedź:
my_hash.values_at(*my_array) #returns [1,6]
4 dla odpowiedzi nr 2
def get_value(*args)
args.inject(@hash, &:fetch)
end
Jeśli chcesz uniknąć iteracji podczas wyszukiwania (co nie wydaje mi się konieczne), musisz spłaszczyć skrót, który ma być przechowywany:
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 dla odpowiedzi № 3
Jeśli wiesz, że struktura skrótu jest zawsze w tym formacie, możesz po prostu zrobić:
holder[:a][:b][:c]
... zwraca „wartość”.