Class: Hash
Class Method Summary collapse
-
.lazy! ⇒ Object
Hash keys become methods, kinda like OpenStruct.
-
.of_arrays ⇒ Object
Returns a new Hash whose values default to empty arrays.
-
.of_integers ⇒ Object
Returns a new Hash whose values default to 0.
-
.of_sets ⇒ Object
Returns a new Hash whose values default to empty sets.
-
.of_unique_ids ⇒ Object
Returns a new Hash which automatically assigns each unique key to an increasing counter.
Instance Method Summary collapse
-
#apply_diff(changes) ⇒ Object
Applies a Hash#diff changeset and returns the transformed hash.
-
#apply_diff!(changes) ⇒ Object
Applies a Hash#diff changeset to this hash.
-
#blank? ⇒ Boolean
‘true’ if the Hash has no entries.
-
#deep_dup ⇒ Object
Duplicate this hash, including hashes nested inside of it.
-
#diff(other) ⇒ Object
Return all the changes necessary to transform ‘self` into `other`.
-
#map_keys(&block) ⇒ Object
Transforms the keys of the hash by passing them into the supplied block, and then using the blocks result as the new key.
-
#map_keys!(&block) ⇒ Object
Runs map_keys on self.
-
#map_values(&block) ⇒ Object
Transforms the values of the hash by passing them into the supplied block, and then using the block’s result as the new value.
-
#map_values!(&block) ⇒ Object
Runs map_values on self.
-
#mkdir_p(path) ⇒ Object
Makes each element in the ‘path` array point to a hash containing the next element in the `path`.
-
#print_tree(level = 0, indent = " ", &block) ⇒ Object
Print the result of ‘tree`.
-
#query(template) ⇒ Object
(also: #mql)
Query a hash using MQL (see: wiki.freebase.com/wiki/MQL_operators for reference).
-
#remove_blank_values ⇒ Object
Returns a new Hash where blank values have been removed.
-
#remove_blank_values! ⇒ Object
Runs “remove_blank_values” on self.
-
#slice(*keys) ⇒ Object
Returns a hash containing only the keys passed as arguments.
-
#slice!(*keys) ⇒ Object
Alters the hash so it contains only the keys passed as arguments.
-
#to_query ⇒ Object
Convert the hash into a GET query.
-
#tree(level = 0, indent = " ") ⇒ Object
Turn some nested hashes into a tree (returns an array of strings, padded on the left with indents.).
Class Method Details
.lazy! ⇒ Object
Hash keys become methods, kinda like OpenStruct. These methods have the lowest priority, so be careful. They will be overridden by any methods on Hash.
133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/epitools/core_ext/hash.rb', line 133 def self.lazy! Hash.class_eval do def method_missing(name, *args) if args.any? super else self[name] || self[name.to_s] end end end end |
.of_arrays ⇒ Object
Returns a new Hash whose values default to empty arrays. (Good for collecting things!)
eg:
Hash.of_arrays[:yays] << "YAY!"
88 89 90 |
# File 'lib/epitools/core_ext/hash.rb', line 88 def self.of_arrays new {|h,k| h[k] = [] } end |
.of_integers ⇒ Object
Returns a new Hash whose values default to 0. (Good for counting things!)
eg:
Hash.of_integers[:yays] += 1
108 109 110 |
# File 'lib/epitools/core_ext/hash.rb', line 108 def self.of_integers new(0) end |
.of_sets ⇒ Object
Returns a new Hash whose values default to empty sets. (Good for collecting unique things!)
eg:
Hash.of_sets[:yays] << "Yay!"
98 99 100 |
# File 'lib/epitools/core_ext/hash.rb', line 98 def self.of_sets new {|h,k| h[k] = Set.new } end |
.of_unique_ids ⇒ Object
Returns a new Hash which automatically assigns each unique key to an increasing counter.
eg:
> h = Hash.of_unique_ids
=> {}
> h["Person"] #=> 0
> h["Another Person"] #=> 1
> h["Yet Another Person"] #=> 2
> h["Person"] #=> 0
> h
=> {"Person"=>0, "Another Person"=>1, "Yet Another Person"=>2}
125 126 127 |
# File 'lib/epitools/core_ext/hash.rb', line 125 def self.of_unique_ids new { |h,k| h[k] = h.size } end |
Instance Method Details
#apply_diff(changes) ⇒ Object
Applies a Hash#diff changeset and returns the transformed hash.
296 297 298 |
# File 'lib/epitools/core_ext/hash.rb', line 296 def apply_diff(changes) deep_dup.apply_diff!(changes) end |
#apply_diff!(changes) ⇒ Object
Applies a Hash#diff changeset to this hash.
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/epitools/core_ext/hash.rb', line 270 def apply_diff!(changes) path = [[self, changes]] pos, local_changes = path.pop while local_changes local_changes.each_pair do |key, change| if change.kind_of?(Array) if change[1].nil? pos.delete key else pos[key] = change[1] end else path.push([pos[key], change]) end end pos, local_changes = path.pop end self end |
#blank? ⇒ Boolean
‘true’ if the Hash has no entries
7 8 9 |
# File 'lib/epitools/core_ext/hash.rb', line 7 def blank? not any? end |
#deep_dup ⇒ Object
Duplicate this hash, including hashes nested inside of it.
303 304 305 306 307 308 309 310 |
# File 'lib/epitools/core_ext/hash.rb', line 303 def deep_dup duplicate = self.dup duplicate.each_pair do |k,v| tv = duplicate[k] duplicate[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_dup : v end duplicate end |
#diff(other) ⇒ Object
Return all the changes necessary to transform ‘self` into `other`. (Works on nested hashes.) The result is a hash of => [old value, new value] pairs.
(NOTE: Since “nil” is used to denote a value was removed, you can’t use this method to diff hashes where a value is “nil”.)
254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/epitools/core_ext/hash.rb', line 254 def diff(other) (self.keys + other.keys).uniq.inject({}) do |memo, key| unless self[key] == other[key] if self[key].kind_of?(Hash) && other[key].kind_of?(Hash) memo[key] = self[key].diff(other[key]) else memo[key] = [self[key], other[key]] end end memo end end |
#map_keys(&block) ⇒ Object
Transforms the keys of the hash by passing them into the supplied block, and then using the blocks result as the new key.
61 62 63 |
# File 'lib/epitools/core_ext/hash.rb', line 61 def map_keys(&block) dup.map_keys!(&block) end |
#map_keys!(&block) ⇒ Object
Runs map_keys on self.
49 50 51 52 53 54 55 |
# File 'lib/epitools/core_ext/hash.rb', line 49 def map_keys!(&block) keys.each do |key| value = delete(key) self[yield(key)] = value end self end |
#map_values(&block) ⇒ Object
Transforms the values of the hash by passing them into the supplied block, and then using the block’s result as the new value.
42 43 44 |
# File 'lib/epitools/core_ext/hash.rb', line 42 def map_values(&block) dup.map_values!(&block) end |
#map_values!(&block) ⇒ Object
Runs map_values on self.
30 31 32 33 34 35 36 |
# File 'lib/epitools/core_ext/hash.rb', line 30 def map_values!(&block) keys.each do |key| value = self[key] self[key] = yield(value) end self end |
#mkdir_p(path) ⇒ Object
Makes each element in the ‘path` array point to a hash containing the next element in the `path`. Useful for turning a bunch of strings (paths, module names, etc.) into a tree.
Example:
h = {}
h.mkdir_p(["a", "b", "c"]) #=> {"a"=>{"b"=>{"c"=>{}}}}
h.mkdir_p(["a", "b", "whoa"]) #=> {"a"=>{"b"=>{"c"=>{}, "whoa"=>{}}}}
160 161 162 163 164 165 166 |
# File 'lib/epitools/core_ext/hash.rb', line 160 def mkdir_p(path) return if path.empty? dir = path.first self[dir] ||= {} self[dir].mkdir_p(path[1..-1]) self end |
#print_tree(level = 0, indent = " ", &block) ⇒ Object
Print the result of ‘tree`
184 185 186 187 188 189 190 191 |
# File 'lib/epitools/core_ext/hash.rb', line 184 def print_tree(level=0, indent=" ", &block) dent = indent * level each do |key, val| puts block_given? ? yield(key, level) : "#{dent}#{key}" val.print_tree(level+1, indent, &block) if val.any? end end |
#query(template) ⇒ Object Also known as: mql
Query a hash using MQL (see: wiki.freebase.com/wiki/MQL_operators for reference)
Examples:
> query(name: /steve/)
> query(/title/ => ??)
> query(articles: [{title: ??}])
> query(responses: [])
> query("date_of_birth<" => "2000")
232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/epitools/core_ext/hash.rb', line 232 def query(template) results = [] template.each do |key,val| case key when Regexp, String when Array when Hash results += hash.query(template) end end map do |key,val| end end |
#remove_blank_values ⇒ Object
Returns a new Hash where blank values have been removed. (It checks if the value is blank by calling #blank? on it)
23 24 25 |
# File 'lib/epitools/core_ext/hash.rb', line 23 def remove_blank_values dup.remove_blank_values! end |
#remove_blank_values! ⇒ Object
Runs “remove_blank_values” on self.
14 15 16 17 |
# File 'lib/epitools/core_ext/hash.rb', line 14 def remove_blank_values! delete_if{|k,v| v.blank?} self end |
#slice(*keys) ⇒ Object
Returns a hash containing only the keys passed as arguments.
68 69 70 |
# File 'lib/epitools/core_ext/hash.rb', line 68 def slice(*keys) dup.slice!(*keys) end |
#slice!(*keys) ⇒ Object
Alters the hash so it contains only the keys passed as arguments.
76 77 78 79 80 |
# File 'lib/epitools/core_ext/hash.rb', line 76 def slice!(*keys) keys = Set.new keys delete_if { |k,v| not keys.include? k } self end |
#to_query ⇒ Object
Convert the hash into a GET query.
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/epitools/core_ext/hash.rb', line 196 def to_query params = '' stack = [] each do |k, v| if v.is_a?(Hash) stack << [k,v] else params << "#{k}=#{v}&" end end stack.each do |parent, hash| hash.each do |k, v| if v.is_a?(Hash) stack << ["#{parent}[#{k}]", v] else params << "#{parent}[#{k}]=#{v}&" end end end params.chop! # trailing & params end |
#tree(level = 0, indent = " ") ⇒ Object
Turn some nested hashes into a tree (returns an array of strings, padded on the left with indents.)
171 172 173 174 175 176 177 178 179 |
# File 'lib/epitools/core_ext/hash.rb', line 171 def tree(level=0, indent=" ") result = [] dent = indent * level each do |key, val| result << dent+key.to_s result += val.tree(level+1) if val.any? end result end |