Module: Gorillib::Hashlike
- Includes:
- Serialization
- Defined in:
- lib/gorillib/hashlike.rb,
lib/gorillib/hashlike/keys.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/deep_compact.rb,
lib/gorillib/serialization/to_wire.rb,
lib/gorillib/serialization/to_wire.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
valwithkey. - 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
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
hshfor whichblockevaluates truthy. -
#each_key ⇒ Object
Hashlike#each_key.
-
#each_value ⇒ Object
Calls
blockonce 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
hshfor whichblockevaluates 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_hashand 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
hshfor whichblockevaluates truthy (equivalent to Hashlike#delete_if), but returns nil if no changes were made. -
#select!(&block) ⇒ Object
Deletes every key-value pair from
hshfor whichblockevaluates 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_hashtohsh. -
#values_of(*allowed_keys) ⇒ Array
Array containing the values associated with the given keys.
Methods included from Serialization
Class Method Details
.included(base) ⇒ Object
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 |
# File 'lib/gorillib/hashlike.rb', line 806 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
KeyErrorexception; - 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 ⇒ Array #flatten(level) ⇒ 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.
802 803 804 |
# File 'lib/gorillib/hashlike.rb', line 802 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 |