Module: Gorillib::Hashlike
- Includes:
- Serialization
- Defined in:
- lib/gorillib/hashlike.rb,
lib/gorillib/hashlike/keys.rb,
lib/gorillib/serialization.rb,
lib/gorillib/serialization.rb,
lib/gorillib/hashlike/slice.rb,
lib/gorillib/hashlike/compact.rb,
lib/gorillib/hashlike/deep_dup.rb,
lib/gorillib/hashlike/deep_hash.rb,
lib/gorillib/hashlike/deep_merge.rb,
lib/gorillib/hashlike/tree_merge.rb,
lib/gorillib/hashlike/deep_compact.rb,
lib/gorillib/hashlike/reverse_merge.rb,
lib/gorillib/hashlike/hashlike_via_accessors.rb
Overview
Your class must provide #[], #[]=, #delete, and #keys –
-
hsh Element Reference – Retrieves the value stored for
key
. -
hsh = val Element Assignment – Associates
val
withkey
. -
hsh.delete(key) Deletes & returns the value whose key is equal to
key
. -
hsh.keys Returns a new array populated with the keys.
(see Hashlike::HashlikeViaAccessors for example)
Given the above, hashlike will provide the rest, defining the methods
:each_pair, :each, :each_key, :each_value, :values_at, :values_of, :values,
:size, :length, :has_key?, :include?, :key?, :member?, :has_value?, :value?,
:fetch, :key, :assoc, :rassoc, :empty?, :merge, :update, :merge!, :reject!,
:select!, :delete_if, :keep_if, :reject, :clear, :store, :to_hash, :invert,
:flatten
and these methods added by Enumerable:
:each_cons, :each_entry, :each_slice, :each_with_index, :each_with_object,
:entries, :to_a, :map, :collect, :collect_concat, :group_by, :flat_map,
:inject, :reduce, :chunk, :reverse_each, :slice_before, :drop, :drop_while,
:take, :take_while, :detect, :find, :find_all, :select, :find_index, :grep,
:all?, :any?, :none?, :one?, :first, :count, :zip, :max, :max_by, :min,
:min_by, :minmax, :minmax_by, :sort, :sort_by, :cycle, :partition,
It does not define these methods that do exist on hash:
:default, :default=, :default_proc, :default_proc=,
:compare_by_identity, :compare_by_identity?,
:replace, :rehash, :shift
Chinese wall
With a few exceptions, all methods are defined only in terms of
#[], #[]=, #delete, #keys, #each_pair and #has_key?
(exceptions: merge family depend on #update; the reject/select/xx_if family depend on each other; #invert & #flatten call #to_hash; #rassoc calls #key)
custom iterators
Hashlike typically defines the following fundamental iterators by including Gorillib::Hashlike::EnumerateFromKeys:
:each_pair, :each, :values, :values_at, :length
However, if the #each_pair method already exists on the class (as it does for Struct), those methods will not be defined. The class is held responsible for the implementation of all five. (Of these, #each_pair is the only method called from elsewhere in Hashlike, while #each is the only method called from Enumerable).
#convert_key (Indifferent Access)
If you define #convert_key the #values_at, #has_key?, #fetch, and #assoc methods will use it to sanitize keys coming in from the outside. It’s assumed that you will do the same with #[], #[]= and #delete. (see Gorillib::HashWithIndifferentAccess for an example).
Defined Under Namespace
Modules: Compact, DeepCompact, DeepDup, DeepHash, DeepMerge, EnumerateFromKeys, HashlikeViaAccessors, Keys, OverrideEnumerable, ReverseMerge, Serialization, Slice, TreeMerge
Class Method Summary collapse
Instance Method Summary collapse
-
#assoc(key) ⇒ Array?
Searches through the hashlike comparing obj with the key using ==.
-
#clear ⇒ Hashlike
Removes all key-value pairs from
hsh
. -
#delete_if(&block) ⇒ Object
Deletes every key-value pair from
hsh
for whichblock
evaluates truthy. -
#each_key ⇒ Object
Hashlike#each_key.
-
#each_value ⇒ Object
Calls
block
once for each key inhsh
, passing the value as a parameter. -
#empty? ⇒ true, false
Returns true if the hashlike contains no key-value pairs, false otherwise.
-
#fetch(key, default = nil) {|key| ... } ⇒ Object
Returns a value from the hashlike for the given key.
-
#flatten(*args) ⇒ Array
Returns a new array that is a one-dimensional flattening of this hashlike.
-
#has_key?(key) ⇒ true, false
Returns true if the given key is present in
hsh
. -
#has_value?(target) ⇒ true, false
Returns true if the given value is present for some key in
hsh
. -
#invert ⇒ Hash
Returns a new hash created by using
hsh
‘s values as keys, and the keys as values. -
#keep_if(&block) ⇒ Object
Deletes every key-value pair from
hsh
for whichblock
evaluates falsy. -
#key(val) ⇒ Object?
Searches the hash for an entry whose value ==
val
, returning the corresponding key. -
#merge(*args, &block) ⇒ Object
Returns a new hashlike containing the contents of
other_hash
and the contents ofhsh
. -
#rassoc(val) ⇒ Array?
Searches through the hashlike comparing obj with the value using ==.
-
#reject!(&block) ⇒ Object
Deletes every key-value pair from
hsh
for whichblock
evaluates truthy (equivalent to Hashlike#delete_if), but returns nil if no changes were made. -
#select!(&block) ⇒ Object
Deletes every key-value pair from
hsh
for whichblock
evaluates falsy (equivalent to Hashlike#keep_if), but returns nil if no changes were made. -
#store(key, val) ⇒ Object
alias for #[]=.
-
#to_hash ⇒ Hash
Returns a hash with each key set to its associated value.
-
#update(other_hash) ⇒ Object
Adds the contents of
other_hash
tohsh
. -
#values_of(*allowed_keys) ⇒ Array
Array containing the values associated with the given keys.
Methods included from Serialization
Class Method Details
.included(base) ⇒ Object
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 |
# File 'lib/gorillib/hashlike.rb', line 804 def self.included(base) base.class_eval do include EnumerateFromKeys unless method_defined?(:each_pair) unless include?(Enumerable) include Enumerable include OverrideEnumerable end # included here so they win out over Enumerable alias_method :include?, :has_key? alias_method :key?, :has_key? alias_method :member?, :has_key? alias_method :value?, :has_value? alias_method :merge!, :update alias_method :size, :length end end |
Instance Method Details
#assoc(key) ⇒ Array?
Searches through the hashlike comparing obj with the key using ==. Returns the key-value pair (two elements array) or nil if no match is found.
427 428 429 430 431 |
# File 'lib/gorillib/hashlike.rb', line 427 def assoc(key) key = convert_key(key) if respond_to?(:convert_key) return unless has_key?(key) [key, self[key]] end |
#clear ⇒ Hashlike
Removes all key-value pairs from hsh
.
730 731 732 |
# File 'lib/gorillib/hashlike.rb', line 730 def clear each_pair{|k,v| delete(k) } end |
#hsh.delete_if ⇒ Hashlike #hsh.delete_if(->an_enumerator) ⇒ Enumerator
Deletes every key-value pair from hsh
for which block
evaluates truthy.
If no block is given, an enumerator is returned instead.
625 626 627 628 629 |
# File 'lib/gorillib/hashlike.rb', line 625 def delete_if(&block) return enum_for(:delete_if) unless block_given? reject!(&block) self end |
#hsh.each_key {|key| ... } ⇒ Hashlike #hsh.each_key(->an_enumerator) ⇒ Enumerator
Hashlike#each_key
Calls block
once for each key in hsh
, passing the key as a parameter.
If no block is given, an enumerator is returned instead.
250 251 252 253 254 |
# File 'lib/gorillib/hashlike.rb', line 250 def each_key return enum_for(:each_key) unless block_given? each_pair{|k,v| yield k } self end |
#hsh.each_value {|val| ... } ⇒ Hashlike #hsh.each_value(->an_enumerator) ⇒ Enumerator
Calls block
once for each key in hsh
, passing the value as a parameter.
If no block is given, an enumerator is returned instead.
287 288 289 290 291 |
# File 'lib/gorillib/hashlike.rb', line 287 def each_value return enum_for(:each_value) unless block_given? each_pair{|k,v| yield v } self end |
#empty? ⇒ true, false
Returns true if the hashlike contains no key-value pairs, false otherwise.
461 462 463 |
# File 'lib/gorillib/hashlike.rb', line 461 def empty? keys.empty? end |
#fetch(key, default = nil) {|key| ... } ⇒ Object
Returns a value from the hashlike for the given key. If the key can’t be found, there are several options:
-
With no other arguments, it will raise a
KeyError
exception; -
if default is given, then that will be returned;
-
if the optional code block is specified, then that will be run and its result returned.
382 383 384 385 386 387 388 389 390 |
# File 'lib/gorillib/hashlike.rb', line 382 def fetch(key, default=nil, &block) key = convert_key(key) if respond_to?(:convert_key) warn "#{caller[0]}: warning: block supersedes default value argument" if default && block_given? if has_key?(key) then self[key] elsif block_given? then yield(key) elsif default then default else raise KeyError, "key not found: #{key.inspect}" end end |
#flatten(*args) ⇒ Array
Returns a new array that is a one-dimensional flattening of this hashlike. That is, for every key or value that is an array, extract its elements into the new array. Unlike Array#flatten, this method does not flatten recursively by default; pass nil
explicitly to flatten recursively. The optional level argument determines the level of recursion to flatten.
800 801 802 |
# File 'lib/gorillib/hashlike.rb', line 800 def flatten(*args) to_hash.flatten(*args) end |
#has_key?(key) ⇒ true, false
Returns true if the given key is present in hsh
.
328 329 330 331 |
# File 'lib/gorillib/hashlike.rb', line 328 def has_key?(key) key = convert_key(key) if respond_to?(:convert_key) keys.include?(key) end |
#has_value?(target) ⇒ true, false
Returns true if the given value is present for some key in hsh
.
344 345 346 347 348 |
# File 'lib/gorillib/hashlike.rb', line 344 def has_value?(target) # don't refactor this to any? -- Struct's #any is weird each_pair{|key, val| return true if (val == target) } false end |
#invert ⇒ Hash
Returns a new hash created by using hsh
‘s values as keys, and the keys as values. If hsh
has duplicate values, the result will contain only one of them as a key – which one is not predictable.
759 760 761 |
# File 'lib/gorillib/hashlike.rb', line 759 def invert to_hash.invert end |
#hsh.keep_if ⇒ Hashlike #hsh.keep_if(->an_enumerator) ⇒ Enumerator
Deletes every key-value pair from hsh
for which block
evaluates falsy.
If no block is given, an enumerator is returned instead.
651 652 653 654 655 |
# File 'lib/gorillib/hashlike.rb', line 651 def keep_if(&block) return enum_for(:keep_if) unless block_given? select!(&block) self end |
#key(val) ⇒ Object?
Searches the hash for an entry whose value == val
, returning the corresponding key. If not found, returns nil
.
You are guaranteed that the first matching key in #keys will be the one returned.
407 408 409 |
# File 'lib/gorillib/hashlike.rb', line 407 def key(val) keys.find{|key| self[key] == val } end |
#hsh.merge(other_hash) ⇒ Hashlike #hsh.merge(other_hash) {|Object, Object, Object| ... } ⇒ Hashlike
Returns a new hashlike containing the contents of other_hash
and the contents of hsh
. If no block is specified, the value for entries with duplicate keys will be that of other_hash
. Otherwise the value for each duplicate key is determined by calling the block with the key, its value in hsh
and its value in other_hash
.
539 540 541 |
# File 'lib/gorillib/hashlike.rb', line 539 def merge(*args, &block) self.dup.update(*args, &block) end |
#rassoc(val) ⇒ Array?
Searches through the hashlike comparing obj with the value using ==. Returns the first key-value pair (two-element array) that matches, or nil if no match is found.
448 449 450 451 |
# File 'lib/gorillib/hashlike.rb', line 448 def rassoc(val) key = key(val) or return [key, self[key]] end |
#hsh.reject! ⇒ Hashlike? #hsh.reject!(->an_enumerator) ⇒ Enumerator
Deletes every key-value pair from hsh
for which block
evaluates truthy (equivalent to Hashlike#delete_if), but returns nil if no changes were made.
562 563 564 565 566 567 568 569 570 571 572 |
# File 'lib/gorillib/hashlike.rb', line 562 def reject!(&block) return enum_for(:reject!) unless block_given? changed = false each_pair do |key, val| if yield(*[key, val].take(block.arity)) changed = true delete(key) end end changed ? self : nil end |
#hsh.select! ⇒ Hashlike #hsh.select!(->an_enumerator) ⇒ Enumerator
Deletes every key-value pair from hsh
for which block
evaluates falsy (equivalent to Hashlike#keep_if), but returns nil if no changes were made.
593 594 595 596 597 598 599 600 601 602 603 |
# File 'lib/gorillib/hashlike.rb', line 593 def select!(&block) return enum_for(:select!) unless block_given? changed = false each_pair do |key, val| if not yield(*[key, val].take(block.arity)) changed = true delete(key) end end changed ? self : nil end |
#store(key, val) ⇒ Object
alias for #[]=
214 215 216 |
# File 'lib/gorillib/hashlike.rb', line 214 def store(key, val) self[key] = val end |
#to_hash ⇒ Hash
Returns a hash with each key set to its associated value.
744 745 746 |
# File 'lib/gorillib/hashlike.rb', line 744 def to_hash {}.tap{|hsh| each_pair{|key, val| hsh[key] = val } } end |
#hsh.update(other_hash) ⇒ Hashlike #hsh.update(other_hash) {|Object, Object, Object| ... } ⇒ Hashlike
Adds the contents of other_hash
to hsh
. If no block is specified, entries with duplicate keys are overwritten with the values from other_hash
, otherwise the value of each duplicate key is determined by calling the block with the key, its value in hsh
and its value in other_hash
.
497 498 499 500 501 502 503 504 505 506 |
# File 'lib/gorillib/hashlike.rb', line 497 def update(other_hash) raise TypeError, "can't convert #{other_hash.nil? ? 'nil' : other_hash.class} into Hash" unless other_hash.respond_to?(:each_pair) other_hash.each_pair do |key, val| if block_given? && has_key?(key) val = yield(key, val, self[key]) end self[key] = val end self end |
#values_of(*allowed_keys) ⇒ Array
Array containing the values associated with the given keys.
310 311 312 313 314 315 |
# File 'lib/gorillib/hashlike.rb', line 310 def values_of(*allowed_keys) allowed_keys.map do |key| key = convert_key(key) if respond_to?(:convert_key) self[key] if has_key?(key) end end |