Abhishek Jain
Abhishek Jain

Reputation: 238

Ruby hash access value from string array

I have an hash like below:

hash = {"a": [{"c": "d", "e": "f"}] }

Normally we can access it like hash["a"][0]["c"].

But, I have a string like:

string = "a[0]['c']"

(This can change depending upon user input)

Is there any easy way to access hash using above string values?

Upvotes: 0

Views: 1510

Answers (3)

Eric Duminil
Eric Duminil

Reputation: 54303

You could do this :

hash = { 'a' => [{ 'c' => 'd', 'e' => 'f' }] }

string = "a[0]['c']"

def nested_access(object, string)
  string.scan(/\w+/).inject(object) do |hash_or_array, i|
    case hash_or_array
    when Array then hash_or_array[i.to_i]
    when Hash then hash_or_array[i] || hash_or_array[i.to_sym]
    end
  end
end

puts nested_access(hash, string) # => "d"

The input string is scanned for letters, underscores and digits. Everything else is ignored :

puts nested_access(hash, "a/0/c") #=> "d"
puts nested_access(hash, "a 0 c") #=> "d"
puts nested_access(hash, "a;0;c") #=> "d"

An incorrect access value will return nil.

It also works with symbol as keys :

hash = {a: [{c: "d", e: "f"}]}
puts nested_access(hash, "['a'][0]['c']")

It brings the advantage of being not too strict about user input, but it does have the drawback of not recognizing keys with spaces.

Upvotes: 1

sa77
sa77

Reputation: 3603

you can use gsub to clean other characters into an array and use that array to access your hash

hash = {"a": [{"c": "d", "e": "f"}] }

string = "a[0]['c']"

tmp = string.gsub(/[\[\]\']/, '').split('')
#=> ["a", "0", "c"]

hash[tmp[0].to_sym][tmp[1].to_i][tmp[2].to_sym]
#=> "d"

Upvotes: 0

ndnenkov
ndnenkov

Reputation: 36110

Assuming that the user inputs numbers for array indices and words for hash keys:

keys = string.scan(/(\d+)|(\w+)/).map do |number, string|
  number&.to_i || string.to_sym
end

hash.dig(*keys) # => "d"

Upvotes: 2

Related Questions