class Hash

Monkey patches

Public Instance Methods

deep_merge(with, merge_arrays: true, overwrite: true, uniq: false) click to toggle source

Merges with another hash but also merges all nested hashes and arrays/values.

# File lib/bblib/core/util/hash.rb, line 4
def deep_merge(with, merge_arrays: true, overwrite: true, uniq: false)
  merger = proc do |_k, v1, v2|
    if BBLib.are_all?(Hash, v1, v2)
      v1.merge(v2, &merger)
    elsif merge_arrays && BBLib.are_all?(Array, v1, v2)
      uniq ? (v1 + v2).uniq : v1 + v2
    else
      overwrite || v1 == v2 ? v2 : (uniq ? [v1, v2].flatten.uniq : [v1, v2].flatten)
    end
  end
  merge(with, &merger)
end
deep_merge!(*args) click to toggle source

In place version of deep_merge

# File lib/bblib/core/util/hash.rb, line 18
def deep_merge!(*args)
  replace deep_merge(*args)
end
diff(hash) click to toggle source

Displays all of the differences between this hash and another. Checks both key and value pairs.

# File lib/bblib/core/util/hash.rb, line 65
def diff(hash)
  to_a.diff(hash.to_a).to_h
end
dive(*keys) click to toggle source

Returns all matching values with a specific key (or keys) recursively within a Hash (including nested Arrays)

# File lib/bblib/core/util/hash.rb, line 70
def dive(*keys)
  matches = []
  each do |k, v|
    matches << v if keys.any? { |key| (key.is_a?(Regexp) ? key =~ k : key == k) }
    matches += v.dive(*keys) if v.respond_to?(:dive)
  end
  matches
end
except(*args) click to toggle source

Returns a version of the hash with the specified keys removed.

# File lib/bblib/core/util/hash.rb, line 135
def except(*args)
  reject { |k, _v| args.include?(k) }
end
expand() click to toggle source

Expands keys in a hash using a delimiter. Opposite of squish.

# File lib/bblib/core/util/hash.rb, line 121
def expand
  {}.to_tree_hash.tap do |hash|
    each do |k, v|
      hash.bridge(k => v)
    end
  end.value
end
hash_path(*path) click to toggle source
# File lib/bblib/core/hash_path/hash_path.rb, line 109
def hash_path(*path)
  BBLib.hash_path self, *path
end
Also aliased as: hpath
hash_path_copy(*paths) click to toggle source
# File lib/bblib/core/hash_path/hash_path.rb, line 117
def hash_path_copy(*paths)
  BBLib.hash_path_copy self, *paths
end
Also aliased as: hpath_copy
hash_path_copy_to(to, *paths) click to toggle source
# File lib/bblib/core/hash_path/hash_path.rb, line 121
def hash_path_copy_to(to, *paths)
  BBLib.hash_path_copy_to self, to, *paths
end
Also aliased as: hpath_copy_to
hash_path_delete(*paths) click to toggle source
# File lib/bblib/core/hash_path/hash_path.rb, line 125
def hash_path_delete(*paths)
  BBLib.hash_path_delete self, *paths
end
Also aliased as: hpath_delete
hash_path_for(value) click to toggle source
# File lib/bblib/core/hash_path/hash_path.rb, line 141
def hash_path_for(value)
  BBLib.hash_path_key_for self, value
end
Also aliased as: hpath_for
hash_path_move(*paths) click to toggle source
# File lib/bblib/core/hash_path/hash_path.rb, line 129
def hash_path_move(*paths)
  BBLib.hash_path_move self, *paths
end
Also aliased as: hpath_move
hash_path_move_to(to, *paths) click to toggle source
# File lib/bblib/core/hash_path/hash_path.rb, line 133
def hash_path_move_to(to, *paths)
  BBLib.hash_path_move_to self, to, *paths
end
Also aliased as: hpath_move_to
hash_path_set(*paths) click to toggle source
# File lib/bblib/core/hash_path/hash_path.rb, line 113
def hash_path_set(*paths)
  BBLib.hash_path_set self, *paths
end
Also aliased as: hpath_set
hash_paths() click to toggle source
# File lib/bblib/core/hash_path/hash_path.rb, line 137
def hash_paths
  BBLib.hash_path_keys self
end
Also aliased as: hpaths
hmap() { |k, v| ... } click to toggle source

Map for hash that automatically converts the yield block to a hash. Each yield must produce an array with exactly two elements.

# File lib/bblib/core/util/hash.rb, line 158
def hmap
  return map unless block_given?
  map { |k, v| yield(k, v) }.compact.to_h
end
hpath(*path)
Alias for: hash_path
hpath_copy(*paths)
Alias for: hash_path_copy
hpath_copy_to(to, *paths)
Alias for: hash_path_copy_to
hpath_delete(*paths)
Alias for: hash_path_delete
hpath_for(value)
Alias for: hash_path_for
hpath_move(*paths)
Alias for: hash_path_move
hpath_move_to(to, *paths)
Alias for: hash_path_move_to
hpath_set(*paths)
Alias for: hash_path_set
hpaths()
Alias for: hash_paths
keys_to_s(recursive: true) click to toggle source

Converts the keys of the hash as well as any nested hashes to strings.

# File lib/bblib/core/util/hash.rb, line 36
def keys_to_s(recursive: true)
  each_with_object({}) do |(k, v), memo|
    memo[k.to_s] = recursive && v.respond_to?(:keys_to_sym) ? v.keys_to_s : v
  end
end
keys_to_s!(recursive: true) click to toggle source

In place version of keys_to_s

# File lib/bblib/core/util/hash.rb, line 43
def keys_to_s!(recursive: true)
  replace(keys_to_s(recursive: recursive))
end
keys_to_sym(clean: false, recursive: true) click to toggle source

Converts the keys of the hash as well as any nested hashes to symbols.

# File lib/bblib/core/util/hash.rb, line 23
def keys_to_sym(clean: false, recursive: true)
  each_with_object({}) do |(k, v), memo|
    key = clean ? k.to_s.to_clean_sym : k.to_s.to_sym
    memo[key] = recursive && v.respond_to?(:keys_to_sym) ? v.keys_to_sym(clean: clean) : v
  end
end
keys_to_sym!(clean: false, recursive: true) click to toggle source

In place version of keys_to_sym

# File lib/bblib/core/util/hash.rb, line 31
def keys_to_sym!(clean: false, recursive: true)
  replace(keys_to_sym(clean: clean, recursive: recursive))
end
kmap() { |k| ... } click to toggle source

Run a map iterator over the keys in the hash without changing the values.

# File lib/bblib/core/util/hash.rb, line 151
def kmap
  return map unless block_given?
  map { |k, v| [yield(k), v] }.to_h
end
only(*args) click to toggle source

Returns a version of the hash not including the specified keys

# File lib/bblib/core/util/hash.rb, line 130
def only(*args)
  select { |k, _v| args.include?(k) }
end
path_nav(obj, path = '', delimiter = '.') { |path, obj| ... } click to toggle source

Navigate a hash using a dot delimited path.

# File lib/bblib/core/util/hash.rb, line 80
def path_nav(obj, path = '', delimiter = '.', &block)
  case obj
  when Hash
    if obj.empty?
      yield path, obj
    else
      obj.each do |k, v|
        path_nav(
          v,
          (path ? [path, k.to_s.gsub(delimiter, "\\#{delimiter}")].join(delimiter) : k.to_s.gsub(delimiter, "\\#{delimiter}")).to_s,
          delimiter,
          &block
        )
      end
    end
  when Array
    if obj.empty?
      yield path, obj
    else
      obj.each_with_index do |ob, index|
        path_nav(
          ob,
          (path ? [path, "[#{index}]"].join(delimiter) : "[#{index}]").to_s,
          delimiter,
          &block
        )
      end
    end
  else
    yield path, obj
  end
end
reverse() click to toggle source

Reverses the order of keys in the Hash

# File lib/bblib/core/util/hash.rb, line 48
def reverse
  to_a.reverse.to_h
end
reverse!() click to toggle source

In place version of reverse

# File lib/bblib/core/util/hash.rb, line 53
def reverse!
  replace(reverse)
end
squish(delimiter: '.') click to toggle source

Turns nested values' keys into delimiter separated paths

# File lib/bblib/core/util/hash.rb, line 114
def squish(delimiter: '.')
  sh = {}
  path_nav(dup, nil, delimiter) { |k, v| sh[k] = v }
  sh
end
to_hash_struct(recursive = true) click to toggle source
# File lib/bblib/core/classes/hash_struct.rb, line 38
def to_hash_struct(recursive = true)
  hash = recursive ? self.hmap { |k, v| [k, v.respond_to?(:to_hash_struct) ? v.to_hash_struct(recursive) : v] } : self
  BBLib::HashStruct.new.merge(hash)
end
to_tree_hash() click to toggle source

Convert this hash into a TreeHash object.

# File lib/bblib/core/util/hash.rb, line 140
def to_tree_hash
  TreeHash.new(self)
end
unshift(hash, value = nil) click to toggle source

Like unshift for Arrays. Adds a key to the beginning of a Hash rather than the end.

# File lib/bblib/core/util/hash.rb, line 58
def unshift(hash, value = nil)
  hash = { hash => value } unless hash.is_a?(Hash)
  replace(hash.merge(self).merge(hash))
end
vmap() { |v| ... } click to toggle source

Run a map iterator over the values in the hash without changing the keys.

# File lib/bblib/core/util/hash.rb, line 145
def vmap
  return map unless block_given?
  map { |k, v| [k, yield(v)] }.to_h
end