Module: DR::CoreExt::Hash
- Defined in:
- lib/dr/ruby_ext/core_modules.rb
Instance Method Summary collapse
-
#add_key(*keys, key, value) ⇒ Object
like set_key, but only set the value if it does not exist.
-
#add_to_key(*keys, key, value, overwrite: false, uniq: true, deep: false) ⇒ Object
like add_key, but consider the value is an Array and add to it.
-
#deep_merge(other_hash, **opts, &block) ⇒ Object
Returns a new hash with +self+ and +other_hash+ merged recursively.
-
#deep_merge!(other_hash, append: :auto, &block) ⇒ Object
Same as +deep_merge+, but modifies +self+.
- #dig_with_default(*args, default: nil) ⇒ Object
- #has_keys?(*keys, key) ⇒ Boolean
-
#inverse ⇒ Object
from a hash [values] produce a hash [keys] there is already Hash#invert using Hash#key which does that, but the difference here is that we flatten Enumerable values h=2, plim: 2, plam: 3 h.invert #=> 3=>:plam h.inverse #=> :plim], 3=>[:plam].
-
#keyed_value(key, sep: "/") ⇒ Object
take a key of the form ploum/plam/plim and return self[:ploum][:plam][:plim].
-
#leafs(nodes) ⇒ Object
from a hash [:bar, :baz], bar: [:plum, :qux], then leaf [:foo] returns [:plum, :qux, :baz].
- #reverse_deep_merge(other_hash) ⇒ Object
- #reverse_merge(other_hash) ⇒ Object
- #set_key(*keys, key, value) ⇒ Object
-
#set_keyed_value(key, value, sep: "/", symbolize: true) ⇒ Object
take a key of the form ploum/plam/plim and return self[:ploum][:plam][:plim]=value.
-
#slice_with_default(*keys, default: nil) ⇒ Object
Adapted from File activesupport/lib/active_support/core_ext/hash/slice.rb, line 22 Note that ruby has Hash#slice, but if the key does not exist, we cannot configure a default.
-
#sort_all ⇒ Object
sort the keys and the values of the hash.
Instance Method Details
#add_key(*keys, key, value) ⇒ Object
like set_key, but only set the value if it does not exist
188 189 190 191 192 193 194 195 196 197 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 188 def add_key(*keys, key, value) i=self keys.each do |k| i.key?(k) or i[k]={} i=i[k] end i.key?(key) or i[key]=value # self i[key] end |
#add_to_key(*keys, key, value, overwrite: false, uniq: true, deep: false) ⇒ Object
like add_key, but consider the value is an Array and add to it
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 199 def add_to_key(*keys, key, value, overwrite: false, uniq: true, deep: false) i=self keys.each do |k| i.key?(k) or i[k]={} i=i[k] end if value.is_a?(Hash) v=i[key] || {} if deep overwrite ? v.deep_merge!(value) : v=value.deep_merge(v) else overwrite ? v.merge!(value) : v=value.merge(v) end else v=i[key] || [] v += Array(value) v.uniq! if uniq end i[key]=v # self end |
#deep_merge(other_hash, **opts, &block) ⇒ Object
Returns a new hash with +self+ and +other_hash+ merged recursively.
h1 = { x: { y: [4,5,6] }, z: [7,8,9] }
h2 = { x: { y: [7,8,9] }, z: 'xyz' }
h1.deep_merge(h2) #=> {x: {y: [7, 8, 9]}, z: "xyz"}
h2.deep_merge(h1) #=> {x: {y: [4, 5, 6]}, z: [7, 8, 9]}
h1.deep_merge(h2) { |key, old, new| Array.wrap(old) + Array.wrap(new) }
#=> {:x=>{:y=>[4, 5, 6, 7, 8, 9]}, :z=>[7, 8, 9, "xyz"]}
Adapted from active support
33 34 35 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 33 def deep_merge(other_hash, **opts, &block) dup.deep_merge!(other_hash, **opts, &block) end |
#deep_merge!(other_hash, append: :auto, &block) ⇒ Object
Same as +deep_merge+, but modifies +self+.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 38 def deep_merge!(other_hash, append: :auto, &block) return self unless other_hash other_hash.each_pair do |k,v| tv = self[k] case when tv.is_a?(Hash) && v.is_a?(Hash) self[k] = tv.deep_merge(v, &block) when tv.is_a?(Array) && v.is_a?(Array) if append==:auto and v.length > 0 && v.first.nil? then #hack: if the array begins with nil, we append the new #value rather than overwrite it v.shift self[k] += v elsif append && append != :auto self[k] += v else self[k] = block && tv ? block.call(k, tv, v) : v end when tv.nil? && v.is_a?(Array) #here we still need to remove nil (see above) if append==:auto and v.length > 0 && v.first.nil? then v.shift self[k]=v else self[k] = block && tv ? block.call(k, tv, v) : v end else self[k] = block && tv ? block.call(k, tv, v) : v end end self end |
#dig_with_default(*args, default: nil) ⇒ Object
163 164 165 166 167 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 163 def dig_with_default(*args, default: nil) r=dig(*args) return default if r.nil? r end |
#has_keys?(*keys, key) ⇒ Boolean
169 170 171 172 173 174 175 176 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 169 def has_keys?(*keys, key) i=self keys.each do |k| i.key?(k) or return false i=i[k] end i.key?(key) end |
#inverse ⇒ Object
from a hash [values] produce a hash [keys] there is already Hash#invert using Hash#key which does that, but the difference here is that we flatten Enumerable values h=2, plim: 2, plam: 3 h.invert #=> 3=>:plam h.inverse #=> :plim], 3=>[:plam]
83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 83 def inverse r={} each_key do |k| values=fetch(k) values=[values] unless values.respond_to?(:each) values.each do |v| r[v]||=[] r[v]<< k end end return r end |
#keyed_value(key, sep: "/") ⇒ Object
take a key of the form ploum/plam/plim and return self[:ploum][:plam][:plim]
107 108 109 110 111 112 113 114 115 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 107 def keyed_value(key, sep: "/") r=self.dup return r if key.empty? key.to_s.split(sep).each do |k| k=k.to_sym if r.key?(k.to_sym) && !r.key?(k) r=r[k] end return r end |
#leafs(nodes) ⇒ Object
from a hash [:bar, :baz], bar: [:plum, :qux], then leaf [:foo] returns [:plum, :qux, :baz]
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 134 def leafs(nodes) =[] #prevent loops r=nodes.dup begin s,r=r,r.map do |n| if key?(n) && !.include?(n) << n fetch(n) else n end end.flatten end until s==r r end |
#reverse_deep_merge(other_hash) ⇒ Object
74 75 76 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 74 def reverse_deep_merge(other_hash) other_hash.deep_merge(self) end |
#reverse_merge(other_hash) ⇒ Object
71 72 73 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 71 def reverse_merge(other_hash) other_hash.merge(self) end |
#set_key(*keys, key, value) ⇒ Object
178 179 180 181 182 183 184 185 186 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 178 def set_key(*keys, key, value) i=self keys.each do |k| i.key?(k) or i[k]={} i=i[k] end i[key]=value # self end |
#set_keyed_value(key, value, sep: "/", symbolize: true) ⇒ Object
take a key of the form ploum/plam/plim and return self[:ploum][:plam][:plim]=value
119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 119 def set_keyed_value(key,value, sep: "/", symbolize: true) r=self *keys,last=key.to_s.split(sep) keys.each do |k| k=k.to_sym if (symbolize || r.key?(k.to_sym)) and !r.key?(k) r[k]={} unless r.key?(k) r=r[k] end last=last.to_sym if symbolize r[last]=value self end |
#slice_with_default(*keys, default: nil) ⇒ Object
Adapted from File activesupport/lib/active_support/core_ext/hash/slice.rb, line 22 Note that ruby has Hash#slice, but if the key does not exist, we cannot configure a default
153 154 155 156 157 158 159 160 161 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 153 def slice_with_default(*keys, default: nil) keys.each_with_object(::Hash.new) do |k, hash| if has_key?(k) || default == :default_proc hash[k] = self[k] else hash[k] = default end end end |
#sort_all ⇒ Object
sort the keys and the values of the hash
97 98 99 100 101 102 103 |
# File 'lib/dr/ruby_ext/core_modules.rb', line 97 def sort_all r=::Hash[self.sort] r.each do |k,v| r[k]=v.sort end return r end |