Skip to content

Instantly share code, notes, and snippets.

@SegFaultAX
Created February 29, 2016 04:56
Show Gist options
  • Save SegFaultAX/c724dc7e8df9289e75c1 to your computer and use it in GitHub Desktop.
Save SegFaultAX/c724dc7e8df9289e75c1 to your computer and use it in GitHub Desktop.
Dotted path expansion for Ruby hashes
def expand_dotted_keys(hash, recursive = true)
deep_merge = lambda do |h1, h2|
merger = proc do |k, v1, v2|
v1.is_a?(Hash) && v2.is_a?(Hash) ? v1.merge(v2, &merger) : v2
end
h1.merge(h2, &merger)
end
recursive_insert = lambda do |h, path, val|
h ||= {}
if path.size == 1
h[path[0]] = val
else
h[path[0]] = recursive_insert.call(h[path[0]], path[1..-1], val)
end
h
end
hash.inject({}) do |memo, (k, v)|
val = recursive && v.is_a?(Hash) ? expand_dotted_keys(v, recursive) : v
sub = recursive_insert.call({}, k.split("."), val)
deep_merge.call(memo, sub)
end
end
a = { "a" => 1 }
b = { "a.b" => 1 }
c = { "a.b.c" => 1 }
d = { "a.b.c" => 1, "e.f.d" => 2 }
e = { "a.b.c" => 1, "e.f.d" => 2, "a.b.d" => 3 }
f = { "a.b" => { "c.d" => 1 } }
g = { "a.b" => { "c.d" => 1 }, "a" => { "b.c.x" => 2 } }
# puts expand_dotted_keys(a).inspect
# puts expand_dotted_keys(b).inspect
# puts expand_dotted_keys(c).inspect
# puts expand_dotted_keys(d).inspect
# puts expand_dotted_keys(e).inspect
puts "with recursive"
puts expand_dotted_keys(g, true).inspect
puts "without recursive"
puts expand_dotted_keys(g, false).inspect
# output:
# with recursive
# {"a"=>{"b"=>{"c"=>{"d"=>1, "x"=>2}}}}
# without recursive
# {"a"=>{"b"=>{"c.d"=>1}, "b.c.x"=>2}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment