Module: Transproc::HashTransformations
- Extended by:
- Registry
- Defined in:
- lib/transproc/hash.rb
Overview
Transformation functions for Hash objects
Constant Summary collapse
- EMPTY_HASH =
{}.freeze
Class Method Summary collapse
-
.accept_keys(hash, keys) ⇒ Hash
Accepts specified keys from a hash.
-
.copy_keys(source_hash, mapping) ⇒ Hash
Copy all keys in a hash using provided mapping hash.
-
.deep_merge(hash, other) ⇒ Hash
Merge a hash recursively.
-
.deep_stringify_keys(hash) ⇒ Hash
Stringify keys in a hash recursively.
-
.deep_symbolize_keys(hash) ⇒ Hash
Symbolize keys in a hash recursively.
-
.eval_values(hash, args, filters = []) ⇒ Object
Recursively evaluate hash values if they are procs/lambdas.
-
.fold(hash, key, tuple_key) ⇒ Hash
Folds array of tuples to array of values from a specified key.
-
.map_keys(source_hash, fn) ⇒ Hash
Map all keys in a hash with the provided transformation function.
-
.map_value(hash, key, fn) ⇒ Hash
Map a key in a hash with the provided transformation function.
-
.map_values(source_hash, fn) ⇒ Hash
Map all values in a hash using transformation function.
-
.nest(hash, root, keys) ⇒ Hash
Nest values from specified keys under a new key.
-
.reject_keys(hash, keys) ⇒ Hash
Rejects specified keys from a hash.
-
.rename_keys(source_hash, mapping) ⇒ Hash
Rename all keys in a hash using provided mapping hash.
-
.split(hash, key, keys) ⇒ Array<Hash>
Splits hash to array by all values from a specified key.
-
.stringify_keys(hash) ⇒ Hash
Stringify all keys in a hash.
-
.symbolize_keys(hash) ⇒ Hash
Symbolize all keys in a hash.
-
.unwrap(source_hash, root, selected = nil, options = EMPTY_HASH) ⇒ Hash
Collapse a nested hash from a specified key.
Methods included from Registry
[], contain?, fetch, import, register, store
Class Method Details
.accept_keys(hash, keys) ⇒ Hash
Accepts specified keys from a hash
228 229 230 |
# File 'lib/transproc/hash.rb', line 228 def self.accept_keys(hash, keys) Hash[hash].slice(*keys) end |
.copy_keys(source_hash, mapping) ⇒ Hash
Copy all keys in a hash using provided mapping hash
189 190 191 192 193 194 195 196 197 |
# File 'lib/transproc/hash.rb', line 189 def self.copy_keys(source_hash, mapping) Hash[source_hash].tap do |hash| mapping.each do |original_key, new_keys| [*new_keys].each do |new_key| hash[new_key] = hash[original_key] end end end end |
.deep_merge(hash, other) ⇒ Hash
Merge a hash recursively
443 444 445 446 447 448 449 450 451 452 |
# File 'lib/transproc/hash.rb', line 443 def self.deep_merge(hash, other) Hash[hash].merge(other) do |_, original_value, new_value| if original_value.respond_to?(:to_hash) && new_value.respond_to?(:to_hash) deep_merge(Hash[original_value], Hash[new_value]) else new_value end end end |
.deep_stringify_keys(hash) ⇒ Hash
Stringify keys in a hash recursively
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/transproc/hash.rb', line 120 def self.deep_stringify_keys(hash) hash.each_with_object({}) do |(key, value), output| output[key.to_s] = case value when Hash deep_stringify_keys(value) when Array value.map { |item| item.is_a?(Hash) ? deep_stringify_keys(item) : item } else value end end end |
.deep_symbolize_keys(hash) ⇒ Hash
Symbolize keys in a hash recursively
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/transproc/hash.rb', line 76 def self.deep_symbolize_keys(hash) hash.each_with_object({}) do |(key, value), output| output[key.to_sym] = case value when Hash deep_symbolize_keys(value) when Array value.map { |item| item.is_a?(Hash) ? deep_symbolize_keys(item) : item } else value end end end |
.eval_values(hash, args, filters = []) ⇒ Object
Recursively evaluate hash values if they are procs/lambdas
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
# File 'lib/transproc/hash.rb', line 405 def self.eval_values(hash, args, filters = []) hash.each_with_object({}) do |(key, value), output| output[key] = case value when Proc if filters.empty? || filters.include?(key) value.call(*args) else value end when Hash eval_values(value, args, filters) when Array value.map { |item| item.is_a?(Hash) ? eval_values(item, args, filters) : item } else value end end end |
.fold(hash, key, tuple_key) ⇒ Hash
Folds array of tuples to array of values from a specified key
340 341 342 |
# File 'lib/transproc/hash.rb', line 340 def self.fold(hash, key, tuple_key) hash.merge(key => ArrayTransformations.extract_key(hash[key], tuple_key)) end |
.map_keys(source_hash, fn) ⇒ Hash
Map all keys in a hash with the provided transformation function
36 37 38 |
# File 'lib/transproc/hash.rb', line 36 def self.map_keys(source_hash, fn) Hash[source_hash].transform_keys!(&fn) end |
.map_value(hash, key, fn) ⇒ Hash
Map a key in a hash with the provided transformation function
248 249 250 |
# File 'lib/transproc/hash.rb', line 248 def self.map_value(hash, key, fn) hash.merge(key => fn[hash[key]]) end |
.map_values(source_hash, fn) ⇒ Hash
Map all values in a hash using transformation function
148 149 150 |
# File 'lib/transproc/hash.rb', line 148 def self.map_values(source_hash, fn) Hash[source_hash].transform_values!(&fn) end |
.nest(hash, root, keys) ⇒ Hash
Nest values from specified keys under a new key
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/transproc/hash.rb', line 263 def self.nest(hash, root, keys) child = {} keys.each do |key| child[key] = hash[key] if hash.key?(key) end output = Hash[hash] child.each_key { |key| output.delete(key) } old_root = hash[root] if old_root.is_a?(Hash) output[root] = old_root.merge(child) else output[root] = child end output end |
.reject_keys(hash, keys) ⇒ Hash
Rejects specified keys from a hash
211 212 213 |
# File 'lib/transproc/hash.rb', line 211 def self.reject_keys(hash, keys) Hash[hash].reject { |k, _| keys.include?(k) } end |
.rename_keys(source_hash, mapping) ⇒ Hash
Rename all keys in a hash using provided mapping hash
171 172 173 174 175 |
# File 'lib/transproc/hash.rb', line 171 def self.rename_keys(source_hash, mapping) Hash[source_hash].tap do |hash| mapping.each { |k, v| hash[v] = hash.delete(k) if hash.key?(k) } end end |
.split(hash, key, keys) ⇒ Array<Hash>
Splits hash to array by all values from a specified key
The operation adds missing keys extracted from the array to regularize the output.
372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/transproc/hash.rb', line 372 def self.split(hash, key, keys) list = Array(hash[key]) return [hash.reject { |k, _| k == key }] if list.empty? existing = list.flat_map(&:keys).uniq grouped = existing - keys ungrouped = existing & keys list = ArrayTransformations.group(list, key, grouped) if grouped.any? list = list.map { |item| item.merge(reject_keys(hash, [key])) } ArrayTransformations.add_keys(list, ungrouped) end |
.stringify_keys(hash) ⇒ Hash
Stringify all keys in a hash
103 104 105 |
# File 'lib/transproc/hash.rb', line 103 def self.stringify_keys(hash) map_keys(hash, Coercions[:to_string].fn) end |
.symbolize_keys(hash) ⇒ Hash
Symbolize all keys in a hash
58 59 60 |
# File 'lib/transproc/hash.rb', line 58 def self.symbolize_keys(hash) map_keys(hash, Coercions[:to_symbol].fn) end |
.unwrap(source_hash, root, selected = nil, options = EMPTY_HASH) ⇒ Hash
Collapse a nested hash from a specified key
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/transproc/hash.rb', line 301 def self.unwrap(source_hash, root, selected = nil, = EMPTY_HASH) return source_hash unless source_hash[root] , selected = selected, nil if .empty? && selected.is_a?(::Hash) add_prefix = ->(key) do combined = [root, key].join('_') root.is_a?(::Symbol) ? combined.to_sym : combined end Hash[source_hash].merge(root => Hash[source_hash[root]]).tap do |hash| nested_hash = hash[root] keys = nested_hash.keys keys &= selected if selected new_keys = [:prefix] ? keys.map(&add_prefix) : keys hash.update(Hash[new_keys.zip(keys.map { |key| nested_hash.delete(key) })]) hash.delete(root) if nested_hash.empty? end end |