-
-
Save Integralist/9503099 to your computer and use it in GitHub Desktop.
hash = { 'foo' => 'bar' } | |
# Version 1 | |
hash = Hash[hash.map { |k, v| [k.to_sym, v] }] | |
# Version 2 | |
hash = hash.reduce({}) do |memo, (k, v)| | |
memo.tap { |m| m[k.to_sym] = v } | |
end | |
# Version 3 | |
hash = hash.reduce({}) do |memo, (k, v)| | |
memo.merge({ k.to_sym => v}) | |
end | |
# None of the above solutions work with a multi-level hash | |
# They only work on the first level: {:foo=>"bar", :level1=>{"level2"=>"baz"}} | |
# The following two variations solve the problem in the same way | |
multi_hash = { 'foo' => 'bar', 'level1' => { 'level2' => 'baz' } } | |
# Modify `Object` | |
class Object | |
def deep_symbolize_keys | |
return self.reduce({}) do |memo, (k, v)| | |
memo.tap { |m| m[k.to_sym] = v.deep_symbolize_keys } | |
end if self.is_a? Hash | |
return self.reduce([]) do |memo, v| | |
memo << v.deep_symbolize_keys; memo | |
end if self.is_a? Array | |
self | |
end | |
end | |
multi_hash = multi_hash.deep_symbolize_keys | |
# Standalone method | |
def symbolize(obj) | |
return obj.reduce({}) do |memo, (k, v)| | |
memo.tap { |m| m[k.to_sym] = symbolize(v) } | |
end if obj.is_a? Hash | |
return obj.reduce([]) do |memo, v| | |
memo << symbolize(v); memo | |
end if obj.is_a? Array | |
obj | |
end | |
multi_hash = symbolize(multi_hash) |
If I'm not wrong, symbolize function must return obj.to_sym
Thanks. I hadn't known about .tap until seeing this example. Handy. I put together a slightly different version of the standalone method to clarify (for myself) the algorithm.
def symbolize(obj)
if obj.is_a? Hash
return obj.inject({}) do |memo, (k, v)|
memo.tap { |m| m[k.to_sym] = symbolize(v) }
end
elsif obj.is_a? Array
return obj.map { |memo| symbolize(memo) }
end
obj
end
Thank you 👍
Sweet, thanks!
A little trick, using just the Ruby libraries:
hash = { 'foo' => 'bar' }
require 'json'
JSON.parse(hash.to_json, { symbolize_names: true })
With multi hash
multi_hash = { 'foo' => 'bar', 'level1' => { 'level2' => 'baz' } }
=> {"foo"=>"bar", "level1"=>{"level2"=>"baz"}}
JSON.parse(multi_hash.to_json, { symbolize_names: true })
=> {:foo=>"bar", :level1=>{:level2=>"baz"}}
Still easier if you use Rails: https://apidock.com/rails/Hash/symbolize_keys
Very nice approach @martinezcoder
Cool Gist!
@Integralist I would like to add deep_symbolize_keys method to nice_hash gem: https://github.com/MarioRuiz/nice_hash
Since it is yours.... feel free to add it to the Hash class on https://github.com/MarioRuiz/nice_hash/blob/master/lib/nice/hash/add_to_ruby.rb
Or if you prefer it I can do it and name you in the code.
awesome!! @martinezcoder
+1