Last active
February 17, 2023 08:16
-
-
Save fractaledmind/6668eac7c623497ba64ec834b05123eb to your computer and use it in GitHub Desktop.
Returns a flat hash where all nested keys are flattened into an array of keys.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# Returns a flat hash where all nested keys are flattened into an array of keys. | |
# | |
# hash = { key: 'value', nested: { key: 'nested_value' }, array: [0, 1, 2] } | |
# flatten_keys_of(hash) | |
# => { [:key]=>"value", [:nested, :key]=>"nested_value", [:array]=>[0, 1, 2] } | |
# | |
# Can also pass a Proc to change how nested keys are flattened: | |
# flatten_keys_of(hash, flattener: ->(*keys) { keys.join('.') }) | |
# => { "key"=>"value", "nested.key"=>"nested_value", "array"=>[0, 1, 2] } | |
# flatten_keys_of(hash, flattener: ->(*keys) { keys.join('-') }) | |
# => { "key"=>"value", "nested-key"=>"nested_value", "array"=>[0, 1, 2] } | |
# flatten_keys_of(hash, flattener: ->(*keys) { keys.map(&:to_s).reduce { |memo, key| memo + "[#{key}]" } }) | |
# => { "key"=>"value", "nested[key]"=>"nested_value", "array"=>[0, 1, 2] } | |
# | |
# Can also determine if array values should be flattened as well: | |
# hash = { person: { age: '28', siblings: ['Tom', 'Sally'] } } | |
# flatten_keys_of(hash, flatten_arrays: true) | |
# => { [:key]=>"value", [:nested, :key]=>"nested_value", [:array, 0]=>0, [:array, 1]=>1, [:array, 2]=>2 } | |
# flatten_keys_of(hash, flattener: ->(*keys) { keys.join('.') }, flatten_arrays: true) | |
# => { "key"=>"value", "nested.key"=>"nested_value", "array.0"=>0, "array.1"=>1, "array.2"=>2 } | |
# refactored from https://stackoverflow.com/a/23861946/2884386 | |
def flatten_keys_of(input, keys = [], output = {}, flattener: ->(*k) { k }, flatten_arrays: false) | |
if input.is_a?(Hash) | |
input.each do |key, value| | |
flatten_keys_of( | |
value, | |
keys + Array[key], | |
output, | |
flattener: flattener, | |
flatten_arrays: flatten_arrays | |
) | |
end | |
elsif input.is_a?(Array) && flatten_arrays | |
input.each_with_index do |value, index| | |
flatten_keys_of( | |
value, | |
keys + Array[index], | |
output, | |
flattener: flattener, | |
flatten_arrays: flatten_arrays | |
) | |
end | |
else | |
return output.merge!(flattener.call(*keys) => input) | |
end | |
output | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment