Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
explode_paths.rb
# Inspiration: https://gist.github.com/potatosalad/760726
def explode_paths(input, klass: Hash, key_delimiter: '__', key_transform: ->(key) { key.to_sym })
recursive_hash = klass.new { |hash, key| hash[key] = klass.new(&hash.default_proc) }
result = input.to_h.reduce(recursive_hash) do |recursive_acc, (input_key_path, input_value)|
keys = input_key_path.to_s.split(key_delimiter).map(&key_transform)
tree = keys.map {|key| [:[], key] }
tree.push([:[]=, tree.pop[1], input_value])
tree.reduce(recursive_acc) do |acc, tree_node|
acc.public_send(tree_node.shift, *tree_node)
end
recursive_acc
end
result.default = klass.new.default
result
end
# ===== Usage =====
#
# hash_input = {
# foo__bar__a: :a,
# foo__bar__b: :b,
# foo__baz__c: :c,
# foo__baz__d: :d
# }
#
# explode_paths(hash_input)
#
# # Outputs:
#
# {
# foo: {
# bar: {
# a: :a,
# b: :b
# },
# baz: {
# c: :c,
# d: :d
# }
# }
# }
#
# # OR
#
# array_input = [
# [:foo__bar__a, :a],
# [:foo__bar__b, :b],
# [:foo__baz__c, :c],
# [:foo__baz__d, :d],
# ]
#
# explode_paths(array_input)
#
# # Outputs:
#
# {
# foo: {
# bar: {
# a: :a,
# b: :b
# },
# baz: {
# c: :c,
# d: :d
# }
# }
# }
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.