问题
I have an array of hashes to write a generic checker for, so I want to pass in the name of a key to be checked. The hash was defined with keys with symbols (colon prefixes). I can't figure out how to use the variable as a key properly. Even though the key exists in the hash, using the variable to access it results in nil.
In IRB I do this:
>> family = { 'husband' => "Homer", 'wife' => "Marge" }
=> {"husband"=>"Homer", "wife"=>"Marge"}
>> somevar = "husband"
=> "husband"
>> family[somevar]
=> "Homer"
>> another_family = { :husband => "Fred", :wife => "Wilma" }
=> {:husband=>"Fred", :wife=>"Wilma"}
>> another_family[somevar]
=> nil
>>
How do I access the hash key through a variable? Perhaps another way to ask is, how do I coerce the variable to a symbol?
回答1:
You want to convert your string to a symbol first:
another_family[somevar.to_sym]
If you want to not have to worry about if your hash is symbol or string, simply convert it to symbolized keys
see: How do I convert a Ruby hash so that all of its keys are symbols?
回答2:
Since your keys are symbols, use symbols as keys.
> hash = { :husband => 'Homer', :wife => 'Marge' }
=> {:husband=>"Homer", :wife=>"Marge"}
> key_variable = :husband
=> :husband
> hash[key_variable]
=> "Homer"
回答3:
You can use the Active Support gem to get access to the with_indifferent_access method:
require 'active_support/core_ext/hash/indifferent_access'
> hash = { somekey: 'somevalue' }.with_indifferent_access
=> {"somekey"=>"somevalue"}
> hash[:somekey]
=> "somevalue"
> hash['somekey']
=> "somevalue"
回答4:
The things that you see as a variable-key in the hash are called Symbol is a structure in Ruby. They're primarily used either as hash keys or for referencing method names. They're immutable, and Only one copy of any symbol exists at a given time, so they save memory.
You can convert a string or symbol with .to_sym or a symbol to string with .to_s to illustrate this let me show this example:
strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]
symbolArray = [:HTML, :CSS, :JavaScript, :Python, :Ruby]
# Add your code below!
symbols = Array.new
strings.each {|x|
symbols.push(x.to_sym)
}
string = Array.new
symbolArray .each {|x|
string.push(x.to_s)
}
print symbols
print string
the result would be:
[:HTML, :CSS, :JavaScript, :Python, :Ruby]
["HTML", "CSS", "JavaScript", "Python", "Ruby"]
In ruby 9.1 you would see the symbols with the colons (:) in the right instead:
movies = { peter_pan: "magic dust", need_4_speed: "hey bro", back_to_the_future: "hey Doc!" }
I just wanted to make this point a litter more didactic so who ever is reading this can used.
One last thing, this is another way to solve your problem:
movie_ratings = {
:memento => 3,
:primer => 3.5,
:the_matrix => 3,
}
# Add your code below!
movie_ratings.each_key {|k|
puts k.to_s
}
result:
memento
primer
the_matrix
回答5:
If you use Rails with ActiveSupport, then do use HashWithIndifferentAccess for flexibility in accessing hash with either string or symbol.
family = HashWithIndifferentAccess.new({
'husband' => "Homer",
'wife' => "Marge"
})
somevar = "husband"
puts family[somevar]
#Homer
somevar = :husband
puts family[somevar]
#Homer
来源:https://stackoverflow.com/questions/25537934/how-to-access-a-symbol-hash-key-using-a-variable-in-ruby