Class: Immutable::Hash
- Inherits:
-
Object
- Object
- Immutable::Hash
- Includes:
- Enumerable
- Defined in:
- lib/immutable/hash.rb
Overview
An ‘Immutable::Hash` maps a set of unique keys to corresponding values, much like a dictionary maps from words to definitions. Given a key, it can store and retrieve an associated value in constant time. If an existing key is stored again, the new value will replace the old. It behaves much like Ruby’s built-in Hash, which we will call RubyHash for clarity. Like RubyHash, two keys that are ‘#eql?` to each other and have the same `#hash` are considered identical in an `Immutable::Hash`.
An ‘Immutable::Hash` can be created in a couple of ways:
Immutable::Hash.new(font_size: 10, font_family: 'Arial')
Immutable::Hash[first_name: 'John', last_name: 'Smith']
Any ‘Enumerable` object which yields two-element `[key, value]` arrays can be used to initialize an `Immutable::Hash`:
Immutable::Hash.new([[:first_name, 'John'], [:last_name, 'Smith']])
Key/value pairs can be added using #put. A new hash is returned and the existing one is left unchanged:
hash = Immutable::Hash[a: 100, b: 200]
hash.put(:c, 500) # => Immutable::Hash[:a => 100, :b => 200, :c => 500]
hash # => Immutable::Hash[:a => 100, :b => 200]
#put can also take a block, which is used to calculate the value to be stored.
hash.put(:a) { |current| current + 200 } # => Immutable::Hash[:a => 300, :b => 200]
Since it is immutable, all methods which you might expect to “modify” a ‘Immutable::Hash` actually return a new hash and leave the existing one unchanged. This means that the `hash = value` syntax from RubyHash cannot be used with `Immutable::Hash`.
Nested data structures can easily be updated using #update_in:
hash = Immutable::Hash["a" => Immutable::Vector[Immutable::Hash["c" => 42]]]
hash.update_in("a", 0, "c") { |value| value + 5 }
# => Immutable::Hash["a" => Immutable::Hash["b" => Immutable::Hash["c" => 47]]]
While an ‘Immutable::Hash` can iterate over its keys or values, it does not guarantee any specific iteration order (unlike RubyHash). Methods like #flatten do not guarantee the order of returned key/value pairs.
Like RubyHash, an ‘Immutable::Hash` can have a default block which is used when looking up a key that does not exist. Unlike RubyHash, the default block will only be passed the missing key, without the hash itself:
hash = Immutable::Hash.new { |missing_key| missing_key * 10 }
hash[5] # => 50
Class Method Summary collapse
-
.[](pairs = nil) ⇒ Hash
Create a new ‘Hash` populated with the given key/value pairs.
-
.alloc(trie = EmptyTrie, block = nil) ⇒ Hash
“Raw” allocation of a new ‘Hash`.
-
.empty ⇒ Hash
Return an empty ‘Hash`.
Instance Method Summary collapse
-
#<(other) ⇒ Boolean
Return true if this ‘Hash` is a proper subset of `other`, which means all its keys are contained in `other` with the identical values, and the two hashes are not identical.
-
#<=(other) ⇒ Boolean
Return true if this ‘Hash` is a subset of `other`, which means all its keys are contained in `other` with the identical values, and the two hashes are not identical.
-
#==(other) ⇒ Boolean
Return true if ‘other` has the same contents as this `Hash`.
-
#>(other) ⇒ Boolean
Return true if this ‘Hash` is a proper superset of `other`, which means all `other`’s keys are contained in this ‘Hash` with identical values, and the two hashes are not identical.
-
#>=(other) ⇒ Boolean
Return true if this ‘Hash` is a superset of `other`, which means all `other`’s keys are contained in this ‘Hash` with identical values.
- #[]= ⇒ Object
-
#assoc(obj) ⇒ Array
Searches through the ‘Hash`, comparing `obj` with each key (using `#==`).
-
#clear ⇒ Hash
Return an empty ‘Hash` instance, of the same class as this one.
-
#default_proc ⇒ Proc
Return the default block if there is one.
-
#delete(key) ⇒ Hash
Return a new ‘Hash` with `key` removed.
-
#dig(key, *rest) ⇒ Object
Return the value of successively indexing into a nested collection.
-
#dup ⇒ Hash
(also: #clone)
Return ‘self`.
-
#each {|key, value| ... } ⇒ self
(also: #each_pair)
Call the block once for each key/value pair in this ‘Hash`, passing the key/value pair as parameters.
-
#each_key {|key| ... } ⇒ self
Call the block once for each key/value pair in this ‘Hash`, passing the key as a parameter.
-
#each_value {|value| ... } ⇒ self
Call the block once for each key/value pair in this ‘Hash`, passing the value as a parameter.
-
#empty? ⇒ Boolean
Return ‘true` if this `Hash` contains no key/value pairs.
-
#eql?(other) ⇒ Boolean
Return true if ‘other` has the same type and contents as this `Hash`.
-
#except(*keys) ⇒ Hash
Return a new ‘Hash` with the associations for all of the given `keys` removed.
-
#fetch(key, default = Undefined) ⇒ Object
Retrieve the value corresponding to the given key object, or use the provided default value or block, or otherwise raise a ‘KeyError`.
-
#fetch_values(*wanted) ⇒ Vector
Return a Vector of the values which correspond to the ‘wanted` keys.
-
#find {|key, value| ... } ⇒ Array
(also: #detect)
Yield ‘[key, value]` pairs until one is found for which the block returns true.
-
#flatten(level = 1) ⇒ Vector
Return a new Vector which is a one-dimensional flattening of this ‘Hash`.
-
#get(key) ⇒ Object
(also: #[])
Retrieve the value corresponding to the provided key object.
-
#hash ⇒ Integer
See ‘Object#hash`.
-
#initialize(pairs = nil) {|key| ... } ⇒ Hash
constructor
A new instance of Hash.
-
#inspect ⇒ String
Return the contents of this ‘Hash` as a programmer-readable `String`.
-
#invert ⇒ Hash
Return a new ‘Hash` created by using keys as values and values as keys.
-
#key(value) ⇒ Object
Searches through the ‘Hash`, comparing `value` with each value (using `#==`).
-
#key?(key) ⇒ Boolean
(also: #has_key?, #include?, #member?)
Return ‘true` if the given key object is present in this `Hash`.
-
#keys ⇒ Set
Return a new Set containing the keys from this ‘Hash`.
-
#map {|key, value| ... } ⇒ Hash
(also: #collect)
Call the block once for each key/value pair in this ‘Hash`, passing the key/value pair as parameters.
- #marshal_dump ⇒ ::Hash
- #marshal_load(dictionary) ⇒ Object
-
#merge(other) {|key, my_value, other_value| ... } ⇒ Hash
Return a new ‘Hash` containing all the key/value pairs from this `Hash` and `other`.
-
#pretty_print(pp) ⇒ Object
Allows this ‘Hash` to be printed at the `pry` console, or using `pp` (from the Ruby standard library), in a way which takes the amount of horizontal space on the screen into account, and which indents nested structures to make them easier to read.
-
#put(key, value = yield(get(key))) {|value| ... } ⇒ Hash
Return a new ‘Hash` with the existing key/value associations, plus an association between the provided key and value.
-
#rassoc(obj) ⇒ Array
Searches through the ‘Hash`, comparing `obj` with each value (using `#==`).
-
#reverse_each {|key, value| ... } ⇒ self
Call the block once for each key/value pair in this ‘Hash`, passing the key/value pair as parameters.
-
#sample ⇒ Array
Return a randomly chosen ‘[key, value]` pair from this `Hash`.
-
#select {|key, value| ... } ⇒ Hash
(also: #find_all, #keep_if)
Return a new ‘Hash` with all the key/value pairs for which the block returns true.
-
#size ⇒ Integer
(also: #length)
Return the number of key/value pairs in this ‘Hash`.
-
#slice(*wanted) ⇒ Hash
Return a new ‘Hash` with only the associations for the `wanted` keys retained.
-
#sort ⇒ Vector
Return a sorted Vector which contains all the ‘[key, value]` pairs in this `Hash` as two-element `Array`s.
-
#sort_by {|key, value| ... } ⇒ Vector
Return a Vector which contains all the ‘[key, value]` pairs in this `Hash` as two-element Arrays.
-
#store(key, value) ⇒ Hash
An alias for #put to match RubyHash’s API.
-
#to_hash ⇒ ::Hash
(also: #to_h)
Convert this ‘Immutable::Hash` to an instance of Ruby’s built-in ‘Hash`.
-
#to_proc ⇒ Proc
Return a ‘Proc` which accepts a key as an argument and returns the value.
-
#update_in(*key_path) {|value| ... } ⇒ Hash
Return a new ‘Hash` with a deeply nested value modified to the result of the given code block.
-
#value?(value) ⇒ Boolean
(also: #has_value?)
Return ‘true` if this `Hash` has one or more keys which map to the provided value.
-
#values ⇒ Vector
Return a new Vector populated with the values from this ‘Hash`.
-
#values_at(*wanted) ⇒ Vector
Return a Vector of the values which correspond to the ‘wanted` keys.
Methods included from Enumerable
#<=>, #compact, #each_index, #grep, #grep_v, #group_by, #join, #partition, #product, #reject, #sum, #to_set
Methods included from Enumerable
Constructor Details
Class Method Details
.[](pairs = nil) ⇒ Hash
Create a new ‘Hash` populated with the given key/value pairs.
72 73 74 |
# File 'lib/immutable/hash.rb', line 72 def [](pairs = nil) (pairs.nil? || pairs.empty?) ? empty : new(pairs) end |
.alloc(trie = EmptyTrie, block = nil) ⇒ Hash
“Raw” allocation of a new ‘Hash`. Used internally to create a new instance quickly after obtaining a modified Trie.
89 90 91 92 93 94 |
# File 'lib/immutable/hash.rb', line 89 def alloc(trie = EmptyTrie, block = nil) obj = allocate obj.instance_variable_set(:@trie, trie) obj.instance_variable_set(:@default, block) obj.freeze end |
.empty ⇒ Hash
Return an empty ‘Hash`. If used on a subclass, returns an empty instance of that class.
80 81 82 |
# File 'lib/immutable/hash.rb', line 80 def empty @empty ||= self.new end |
Instance Method Details
#<(other) ⇒ Boolean
Return true if this ‘Hash` is a proper subset of `other`, which means all its keys are contained in `other` with the identical values, and the two hashes are not identical.
807 808 809 |
# File 'lib/immutable/hash.rb', line 807 def <(other) other > self end |
#<=(other) ⇒ Boolean
Return true if this ‘Hash` is a subset of `other`, which means all its keys are contained in `other` with the identical values, and the two hashes are not identical.
817 818 819 |
# File 'lib/immutable/hash.rb', line 817 def <=(other) other >= self end |
#==(other) ⇒ Boolean
Return true if ‘other` has the same contents as this `Hash`. Will convert `other` to a Ruby `Hash` using `#to_hash` if necessary.
773 774 775 |
# File 'lib/immutable/hash.rb', line 773 def ==(other) self.eql?(other) || (other.respond_to?(:to_hash) && to_hash.eql?(other.to_hash)) end |
#>(other) ⇒ Boolean
Return true if this ‘Hash` is a proper superset of `other`, which means all `other`’s keys are contained in this ‘Hash` with identical values, and the two hashes are not identical.
783 784 785 |
# File 'lib/immutable/hash.rb', line 783 def >(other) self != other && self >= other end |
#>=(other) ⇒ Boolean
Return true if this ‘Hash` is a superset of `other`, which means all `other`’s keys are contained in this ‘Hash` with identical values.
792 793 794 795 796 797 798 799 |
# File 'lib/immutable/hash.rb', line 792 def >=(other) other.each do |key, value| if self[key] != value return false end end true end |
#[]= ⇒ Object
269 270 271 |
# File 'lib/immutable/hash.rb', line 269 def []=(*) raise NoMethodError, "Immutable::Hash doesn't support `[]='; use `put' instead" end |
#assoc(obj) ⇒ Array
Searches through the ‘Hash`, comparing `obj` with each key (using `#==`). When a matching key is found, return the `[key, value]` pair as an array. Return `nil` if no match is found.
701 702 703 704 |
# File 'lib/immutable/hash.rb', line 701 def assoc(obj) each { |entry| return entry if obj == entry[0] } nil end |
#clear ⇒ Hash
Return an empty ‘Hash` instance, of the same class as this one. Useful if you have multiple subclasses of `Hash` and want to treat them polymorphically. Maintains the default block, if there is one.
751 752 753 754 755 756 757 |
# File 'lib/immutable/hash.rb', line 751 def clear if @default self.class.alloc(EmptyTrie, @default) else self.class.empty end end |
#default_proc ⇒ Proc
Return the default block if there is one. Otherwise, return ‘nil`.
109 110 111 |
# File 'lib/immutable/hash.rb', line 109 def default_proc @default end |
#delete(key) ⇒ Hash
Return a new ‘Hash` with `key` removed. If `key` is not present, return `self`.
328 329 330 |
# File 'lib/immutable/hash.rb', line 328 def delete(key) derive_new_hash(@trie.delete(key)) end |
#dig(key, *rest) ⇒ Object
Return the value of successively indexing into a nested collection. If any of the keys is not present, return ‘nil`.
618 619 620 621 622 623 624 625 |
# File 'lib/immutable/hash.rb', line 618 def dig(key, *rest) value = self[key] if rest.empty? || value.nil? value else value.dig(*rest) end end |
#dup ⇒ Hash Also known as: clone
Return ‘self`. Since this is an immutable object duplicates are equivalent.
849 850 851 |
# File 'lib/immutable/hash.rb', line 849 def dup self end |
#each {|key, value| ... } ⇒ self Also known as: each_pair
Call the block once for each key/value pair in this ‘Hash`, passing the key/value pair as parameters. No specific iteration order is guaranteed, though the order will be stable for any particular `Hash`.
346 347 348 349 350 |
# File 'lib/immutable/hash.rb', line 346 def each(&block) return to_enum if not block_given? @trie.each(&block) self end |
#each_key {|key| ... } ⇒ self
Call the block once for each key/value pair in this ‘Hash`, passing the key as a parameter. Ordering guarantees are the same as #each.
385 386 387 388 389 |
# File 'lib/immutable/hash.rb', line 385 def each_key return enum_for(:each_key) if not block_given? @trie.each { |k,v| yield k } self end |
#each_value {|value| ... } ⇒ self
Call the block once for each key/value pair in this ‘Hash`, passing the value as a parameter. Ordering guarantees are the same as #each.
404 405 406 407 408 |
# File 'lib/immutable/hash.rb', line 404 def each_value return enum_for(:each_value) if not block_given? @trie.each { |k,v| yield v } self end |
#empty? ⇒ Boolean
Return ‘true` if this `Hash` contains no key/value pairs.
127 128 129 |
# File 'lib/immutable/hash.rb', line 127 def empty? @trie.empty? end |
#eql?(other) ⇒ Boolean
Return true if ‘other` has the same type and contents as this `Hash`.
763 764 765 766 |
# File 'lib/immutable/hash.rb', line 763 def eql?(other) return true if other.equal?(self) instance_of?(other.class) && @trie.eql?(other.instance_variable_get(:@trie)) end |
#except(*keys) ⇒ Hash
Return a new ‘Hash` with the associations for all of the given `keys` removed.
560 561 562 |
# File 'lib/immutable/hash.rb', line 560 def except(*keys) keys.reduce(self) { |hash, key| hash.delete(key) } end |
#fetch(key) ⇒ Object #fetch(key) {|key| ... } ⇒ Object #fetch(key, default) ⇒ Object
Retrieve the value corresponding to the given key object, or use the provided default value or block, or otherwise raise a ‘KeyError`.
220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/immutable/hash.rb', line 220 def fetch(key, default = Undefined) entry = @trie.get(key) if entry entry[1] elsif block_given? yield(key) elsif default != Undefined default else raise KeyError, "key not found: #{key.inspect}" end end |
#fetch_values(*wanted) ⇒ Vector
Return a Vector of the values which correspond to the ‘wanted` keys. If any of the `wanted` keys are not present in this `Hash`, raise `KeyError` exception.
604 605 606 607 |
# File 'lib/immutable/hash.rb', line 604 def fetch_values(*wanted) array = wanted.map { |key| fetch(key) } Vector.new(array.freeze) end |
#find {|key, value| ... } ⇒ Array Also known as: detect
Yield ‘[key, value]` pairs until one is found for which the block returns true. Return that `[key, value]` pair. If the block never returns true, return `nil`.
456 457 458 459 460 |
# File 'lib/immutable/hash.rb', line 456 def find return enum_for(:find) unless block_given? each { |entry| return entry if yield entry } nil end |
#flatten(level = 1) ⇒ Vector
Return a new Vector which is a one-dimensional flattening of this ‘Hash`. If `level` is 1, all the `[key, value]` pairs in the hash will be concatenated into one Vector. If `level` is greater than 1, keys or values which are themselves `Array`s or Vectors will be recursively flattened into the output Vector. The depth to which that flattening will be recursively applied is determined by `level`.
As a special case, if ‘level` is 0, each `[key, value]` pair will be a separate element in the returned Vector.
684 685 686 687 688 689 690 |
# File 'lib/immutable/hash.rb', line 684 def flatten(level = 1) return Vector.new(self) if level == 0 array = [] each { |k,v| array << k; array << v } array.flatten!(level-1) if level > 1 Vector.new(array.freeze) end |
#get(key) ⇒ Object Also known as: []
Retrieve the value corresponding to the provided key object. If not found, and this ‘Hash` has a default block, the default block is called to provide the value. Otherwise, return `nil`.
177 178 179 180 181 182 183 184 |
# File 'lib/immutable/hash.rb', line 177 def get(key) entry = @trie.get(key) if entry entry[1] elsif @default @default.call(key) end end |
#hash ⇒ Integer
See ‘Object#hash`.
823 824 825 826 827 |
# File 'lib/immutable/hash.rb', line 823 def hash keys.to_a.sort.reduce(0) do |hash, key| (hash << 32) - hash + key.hash + get(key).hash end end |
#inspect ⇒ String
Return the contents of this ‘Hash` as a programmer-readable `String`. If all the keys and values are serializable as Ruby literal strings, the returned string can be passed to `eval` to reconstitute an equivalent `Hash`. The default block (if there is one) will be lost when doing this, however.
835 836 837 838 839 840 841 842 843 844 |
# File 'lib/immutable/hash.rb', line 835 def inspect result = "#{self.class}[" i = 0 each do |key, val| result << ', ' if i > 0 result << key.inspect << ' => ' << val.inspect i += 1 end result << "]" end |
#invert ⇒ Hash
Return a new ‘Hash` created by using keys as values and values as keys. If there are multiple values which are equivalent (as determined by `#hash` and `#eql?`), only one out of each group of equivalent values will be retained. Which one specifically is undefined.
659 660 661 662 663 |
# File 'lib/immutable/hash.rb', line 659 def invert pairs = [] each { |k,v| pairs << [v, k] } self.class.new(pairs, &@default) end |
#key(value) ⇒ Object
Searches through the ‘Hash`, comparing `value` with each value (using `#==`). When a matching value is found, return its associated key object. Return `nil` if no match is found.
729 730 731 732 |
# File 'lib/immutable/hash.rb', line 729 def key(value) each { |entry| return entry[0] if value == entry[1] } nil end |
#key?(key) ⇒ Boolean Also known as: has_key?, include?, member?
Return ‘true` if the given key object is present in this `Hash`. More precisely, return `true` if a key with the same `#hash` code, and which is also `#eql?` to the given key object is present.
140 141 142 |
# File 'lib/immutable/hash.rb', line 140 def key?(key) @trie.key?(key) end |
#keys ⇒ Set
Return a new Set containing the keys from this ‘Hash`.
634 635 636 |
# File 'lib/immutable/hash.rb', line 634 def keys Set.alloc(@trie) end |
#map {|key, value| ... } ⇒ Hash Also known as: collect
Call the block once for each key/value pair in this ‘Hash`, passing the key/value pair as parameters. The block should return a `[key, value]` array each time. All the returned `[key, value]` arrays will be gathered into a new `Hash`.
421 422 423 424 425 |
# File 'lib/immutable/hash.rb', line 421 def map return enum_for(:map) unless block_given? return self if empty? self.class.new(super, &@default) end |
#marshal_dump ⇒ ::Hash
906 907 908 |
# File 'lib/immutable/hash.rb', line 906 def marshal_dump to_hash end |
#marshal_load(dictionary) ⇒ Object
911 912 913 |
# File 'lib/immutable/hash.rb', line 911 def marshal_load(dictionary) @trie = Trie[dictionary] end |
#merge(other) {|key, my_value, other_value| ... } ⇒ Hash
Return a new ‘Hash` containing all the key/value pairs from this `Hash` and `other`. If no block is provided, the value for entries with colliding keys will be that from `other`. Otherwise, the value for each duplicate key is determined by calling the block.
‘other` can be an `Immutable::Hash`, a built-in Ruby `Hash`, or any `Enumerable` object which yields `[key, value]` pairs.
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
# File 'lib/immutable/hash.rb', line 485 def merge(other) trie = if block_given? other.reduce(@trie) do |trie, (key, value)| if entry = trie.get(key) trie.put(key, yield(key, entry[1], value)) else trie.put(key, value) end end else @trie.bulk_put(other) end derive_new_hash(trie) end |
#pretty_print(pp) ⇒ Object
Allows this ‘Hash` to be printed at the `pry` console, or using `pp` (from the Ruby standard library), in a way which takes the amount of horizontal space on the screen into account, and which indents nested structures to make them easier to read.
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 |
# File 'lib/immutable/hash.rb', line 860 def pretty_print(pp) pp.group(1, "#{self.class}[", "]") do pp.breakable '' pp.seplist(self, nil) do |key, val| pp.group do key.pretty_print(pp) pp.text ' => ' pp.group(1) do pp.breakable '' val.pretty_print(pp) end end end end end |
#put(key, value = yield(get(key))) {|value| ... } ⇒ Hash
Return a new ‘Hash` with the existing key/value associations, plus an association between the provided key and value. If an equivalent key is already present, its associated value will be replaced with the provided one.
If the ‘value` argument is missing, but an optional code block is provided, it will be passed the existing value (or `nil` if there is none) and what it returns will replace the existing value. This is useful for “transforming” the value associated with a certain key.
Avoid mutating objects which are used as keys. ‘String`s are an exception: unfrozen `String`s which are used as keys are internally duplicated and frozen. This matches RubyHash’s behaviour.
258 259 260 261 262 263 264 265 |
# File 'lib/immutable/hash.rb', line 258 def put(key, value = yield(get(key))) new_trie = @trie.put(key, value) if new_trie.equal?(@trie) self else self.class.alloc(new_trie, @default) end end |
#rassoc(obj) ⇒ Array
Searches through the ‘Hash`, comparing `obj` with each value (using `#==`). When a matching value is found, return the `[key, value]` pair as an array. Return `nil` if no match is found.
715 716 717 718 |
# File 'lib/immutable/hash.rb', line 715 def rassoc(obj) each { |entry| return entry if obj == entry[1] } nil end |
#reverse_each {|key, value| ... } ⇒ self
Call the block once for each key/value pair in this ‘Hash`, passing the key/value pair as parameters. Iteration order will be the opposite of #each.
366 367 368 369 370 |
# File 'lib/immutable/hash.rb', line 366 def reverse_each(&block) return enum_for(:reverse_each) if not block_given? @trie.reverse_each(&block) self end |
#sample ⇒ Array
Return a randomly chosen ‘[key, value]` pair from this `Hash`. If the hash is empty, return `nil`.
742 743 744 |
# File 'lib/immutable/hash.rb', line 742 def sample @trie.at(rand(size)) end |
#select {|key, value| ... } ⇒ Hash Also known as: find_all, keep_if
Return a new ‘Hash` with all the key/value pairs for which the block returns true.
438 439 440 441 |
# File 'lib/immutable/hash.rb', line 438 def select(&block) return enum_for(:select) unless block_given? derive_new_hash(@trie.select(&block)) end |
#size ⇒ Integer Also known as: length
Return the number of key/value pairs in this ‘Hash`.
119 120 121 |
# File 'lib/immutable/hash.rb', line 119 def size @trie.size end |
#slice(*wanted) ⇒ Hash
Return a new ‘Hash` with only the associations for the `wanted` keys retained.
572 573 574 575 576 |
# File 'lib/immutable/hash.rb', line 572 def slice(*wanted) trie = Trie.new(0) wanted.each { |key| trie.put!(key, get(key)) if key?(key) } self.class.alloc(trie, @default) end |
#sort ⇒ Vector #sort({ |(k1, v1), (k2, v2)| ... }) {|(k1, v1), (k2, v2)| ... } ⇒ Vector
Return a sorted Vector which contains all the ‘[key, value]` pairs in this `Hash` as two-element `Array`s.
529 530 531 |
# File 'lib/immutable/hash.rb', line 529 def sort Vector.new(super) end |
#sort_by {|key, value| ... } ⇒ Vector
Return a Vector which contains all the ‘[key, value]` pairs in this `Hash` as two-element Arrays. The order which the pairs will appear in is determined by passing each pair to the code block to obtain a sort key object, and comparing the sort keys using `#<=>`.
548 549 550 |
# File 'lib/immutable/hash.rb', line 548 def sort_by Vector.new(super) end |
#store(key, value) ⇒ Hash
315 316 317 |
# File 'lib/immutable/hash.rb', line 315 def store(key, value) put(key, value) end |
#to_hash ⇒ ::Hash Also known as: to_h
Convert this ‘Immutable::Hash` to an instance of Ruby’s built-in ‘Hash`.
879 880 881 882 883 884 885 |
# File 'lib/immutable/hash.rb', line 879 def to_hash output = {} each do |key, value| output[key] = value end output end |
#to_proc ⇒ Proc
Return a ‘Proc` which accepts a key as an argument and returns the value. The `Proc` behaves like #get (when the key is missing, it returns nil or the result of the default proc).
900 901 902 |
# File 'lib/immutable/hash.rb', line 900 def to_proc lambda { |key| get(key) } end |
#update_in(*key_path) {|value| ... } ⇒ Hash
Return a new ‘Hash` with a deeply nested value modified to the result of the given code block. When traversing the nested `Hash`es and `Vector`s, non-existing keys are created with empty `Hash` values.
The code block receives the existing value of the deeply nested key (or ‘nil` if it doesn’t exist). This is useful for “transforming” the value associated with a certain key.
Note that the original ‘Hash` and sub-`Hash`es and sub-`Vector`s are left unmodified; new data structure copies are created along the path wherever needed.
294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/immutable/hash.rb', line 294 def update_in(*key_path, &block) if key_path.empty? raise ArgumentError, "must have at least one key in path" end key = key_path[0] if key_path.size == 1 new_value = block.call(get(key)) else value = fetch(key, EmptyHash) new_value = value.update_in(*key_path[1..-1], &block) end put(key, new_value) end |
#value?(value) ⇒ Boolean Also known as: has_value?
Return ‘true` if this `Hash` has one or more keys which map to the provided value.
154 155 156 157 |
# File 'lib/immutable/hash.rb', line 154 def value?(value) each { |k,v| return true if value == v } false end |
#values ⇒ Vector
Return a new Vector populated with the values from this ‘Hash`.
645 646 647 |
# File 'lib/immutable/hash.rb', line 645 def values Vector.new(each_value.to_a.freeze) end |