class Hamster::Hash

A `Hamster::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 a `Hamster::Hash`.

A `Hamster::Hash` can be created in a couple of ways:

Hamster::Hash.new(font_size: 10, font_family: 'Arial')
Hamster::Hash[first_name: 'John', last_name: 'Smith']

Any `Enumerable` object which yields two-element `[key, value]` arrays can be used to initialize a `Hamster::Hash`:

Hamster::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 = Hamster::Hash[a: 100, b: 200]
hash.put(:c, 500) # => Hamster::Hash[:a => 100, :b => 200, :c => 500]
hash              # => Hamster::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 } # => Hamster::Hash[:a => 300, :b => 200]

Since it is immutable, all methods which you might expect to “modify” a `Hamster::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 `Hamster::Hash`.

Nested data structures can easily be updated using {#update_in}:

hash = Hamster::Hash["a" => Hamster::Vector[Hamster::Hash["c" => 42]]]
hash.update_in("a", 0, "c") { |value| value + 5 }
# => Hamster::Hash["a" => Hamster::Hash["b" => Hamster::Hash["c" => 47]]]

While a `Hamster::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, a `Hamster::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 = Hamster::Hash.new { |missing_key| missing_key * 10 }
hash[5] # => 50

Public Class Methods

[](pairs = nil) click to toggle source

Create a new `Hash` populated with the given key/value pairs.

@example

Hamster::Hash["A" => 1, "B" => 2] # => Hamster::Hash["A" => 1, "B" => 2]
Hamster::Hash[["A", 1], ["B", 2]] # => Hamster::Hash["A" => 1, "B" => 2]

@param pairs [::Enumerable] initial content of hash. An empty hash is returned if not provided. @return [Hash]

# File lib/hamster/hash.rb, line 75
def [](pairs = nil)
  (pairs.nil? || pairs.empty?) ? empty : new(pairs)
end
alloc(trie = EmptyTrie, block = nil) click to toggle source

“Raw” allocation of a new `Hash`. Used internally to create a new instance quickly after obtaining a modified {Trie}.

@return [Hash] @private

# File lib/hamster/hash.rb, line 92
def alloc(trie = EmptyTrie, block = nil)
  obj = allocate
  obj.instance_variable_set(:@trie, trie)
  obj.instance_variable_set(:@default, block)
  obj
end
empty() click to toggle source

Return an empty `Hash`. If used on a subclass, returns an empty instance of that class.

@return [Hash]

# File lib/hamster/hash.rb, line 83
def empty
  @empty ||= self.new
end
new(pairs = nil, &block) click to toggle source

@param pairs [::Enumerable] initial content of hash. An empty hash is returned if not provided. @yield [key] Optional _default block_ to be stored and used to calculate the default value of a missing key. It will not be yielded during this method. It will not be preserved when marshalling. @yieldparam key Key that was not present in the hash.

# File lib/hamster/hash.rb, line 103
def initialize(pairs = nil, &block)
  @trie = pairs ? Trie[pairs] : EmptyTrie
  @default = block
end

Public Instance Methods

<(other) click to toggle source

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.

@param other [Hamster::Hash] The object to compare with @return [Boolean]

# File lib/hamster/hash.rb, line 773
def <(other)
  other > self
end
<=(other) click to toggle source

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.

@param other [Hamster::Hash] The object to compare with @return [Boolean]

# File lib/hamster/hash.rb, line 783
def <=(other)
  other >= self
end
==(other) click to toggle source

Return true if `other` has the same contents as this `Hash`. Will convert `other` to a Ruby `Hash` using `#to_hash` if necessary.

@param other [Object] The object to compare with @return [Boolean]

# File lib/hamster/hash.rb, line 739
def ==(other)
  self.eql?(other) || (other.respond_to?(:to_hash) && to_hash.eql?(other.to_hash))
end
>(other) click to toggle source

Return true if this `Hash` is a proper superset of `other`, which means all `other`'s keys are contained in this `Hash` with the identical values, and the two hashes are not identical.

@param other [Hamster::Hash] The object to compare with @return [Boolean]

# File lib/hamster/hash.rb, line 749
def >(other)
  self != other && self >= other
end
>=(other) click to toggle source

Return true if this `Hash` is a superset of `other`, which means all `other`'s keys are contained in this `Hash` with the identical values.

@param other [Hamster::Hash] The object to compare with @return [Boolean]

# File lib/hamster/hash.rb, line 758
def >=(other)
  other.each do |key, value|
    if self[key] != value
      return false
    end
  end
  true
end
[](key)
Alias for: get
assoc(obj) click to toggle source

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.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].assoc("B")  # => ["B", 2]

@param obj [Object] The key to search for (using #==) @return [Array]

# File lib/hamster/hash.rb, line 667
def assoc(obj)
  each { |entry| return entry if obj == entry[0] }
  nil
end
clear() click to toggle source

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.

@return [Hash]

# File lib/hamster/hash.rb, line 717
def clear
  if @default
    self.class.alloc(EmptyTrie, @default)
  else
    self.class.empty
  end
end
collect()
Alias for: map
default_proc() click to toggle source

Return the default block if there is one. Otherwise, return `nil`.

@return [Proc]

# File lib/hamster/hash.rb, line 111
def default_proc
  @default
end
delete(key) click to toggle source

Return a new `Hash` with `key` removed. If `key` is not present, return `self`.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].delete("B")
# => Hamster::Hash["A" => 1, "C" => 3]

@param key [Object] The key to remove @return [Hash]

# File lib/hamster/hash.rb, line 311
def delete(key)
  derive_new_hash(@trie.delete(key))
end
detect()
Alias for: find
each(&block) click to toggle source

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`.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].each { |k, v| puts "k=#{k} v=#{v}" }

k=A v=1
k=C v=3
k=B v=2
# => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]

@yield [key, value] Once for each key/value pair. @return [self]

# File lib/hamster/hash.rb, line 329
def each(&block)
  return to_enum if not block_given?
  @trie.each(&block)
  self
end
Also aliased as: each_pair
each_key() { |k| ... } click to toggle source

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}.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].each_key { |k| puts "k=#{k}" }

k=A
k=C
k=B
# => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]

@yield [key] Once for each key/value pair. @return [self]

# File lib/hamster/hash.rb, line 368
def each_key
  return enum_for(:each_key) if not block_given?
  @trie.each { |k,v| yield k }
  self
end
each_pair(&block)
Alias for: each
each_value() { |v| ... } click to toggle source

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}.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].each_value { |v| puts "v=#{v}" }

v=1
v=3
v=2
# => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]

@yield [value] Once for each key/value pair. @return [self]

# File lib/hamster/hash.rb, line 387
def each_value
  return enum_for(:each_value) if not block_given?
  @trie.each { |k,v| yield v }
  self
end
empty?() click to toggle source

Return `true` if this `Hash` contains no key/value pairs.

@return [Boolean]

# File lib/hamster/hash.rb, line 129
def empty?
  @trie.empty?
end
eql?(other) click to toggle source

Return true if `other` has the same type and contents as this `Hash`.

@param other [Object] The collection to compare with @return [Boolean]

# File lib/hamster/hash.rb, line 729
def eql?(other)
  return true if other.equal?(self)
  instance_of?(other.class) && @trie.eql?(other.instance_variable_get(:@trie))
end
except(*keys) click to toggle source

Return a new `Hash` with the associations for all of the given `keys` removed.

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.except("A", "C")  # => Hamster::Hash["B" => 2]

@param keys [Array] The keys to remove @return [Hash]

# File lib/hamster/hash.rb, line 543
def except(*keys)
  keys.reduce(self) { |hash, key| hash.delete(key) }
end
fetch(key, default = Undefined) { |key| ... } click to toggle source

Retrieve the value corresponding to the given key object, or use the provided default value or block, or otherwise raise a `KeyError`.

@overload fetch(key)

Retrieve the value corresponding to the given key, or raise a `KeyError`
if it is not found.
@param key [Object] The key to look up

@overload fetch(key) { |key| … }

Retrieve the value corresponding to the given key, or call the optional
code block (with the missing key) and get its return value.
@yield [key] The key which was not found
@yieldreturn [Object] Object to return since the key was not found
@param key [Object] The key to look up

@overload fetch(key, default)

Retrieve the value corresponding to the given key, or else return
the provided `default` value.
@param key [Object] The key to look up
@param default [Object] Object to return if the key is not found

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.fetch("B")         # => 2
h.fetch("Elephant")  # => KeyError: key not found: "Elephant"

# with a default value:
h.fetch("B", 99)         # => 2
h.fetch("Elephant", 99)  # => 99

# with a block:
h.fetch("B") { |key| key.size }         # => 2
h.fetch("Elephant") { |key| key.size }  # => 8

@return [Object]

# File lib/hamster/hash.rb, line 222
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) click to toggle source

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.

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.fetch_values("C", "A")  # => Hamster::Vector[3, 1]
h.fetch_values("C", "Z")  # => KeyError: key not found: "Z"

@param wanted [Array] The keys to retrieve @return [Vector]

# File lib/hamster/hash.rb, line 588
def fetch_values(*wanted)
  array = wanted.map { |key| fetch(key) }
  Vector.new(array.freeze)
end
find() { |entry| ... } click to toggle source

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`.

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.find { |k, v| v.even? }
# => ["B", 2]

@return [Array] @yield [key, value] At most once for each key/value pair, until the block returns `true`. @yieldreturn Truthy to halt iteration and return the yielded key/value pair.

# File lib/hamster/hash.rb, line 439
def find
  return enum_for(:find) unless block_given?
  each { |entry| return entry if yield entry }
  nil
end
Also aliased as: detect
find_all(&block)
Alias for: select
flatten(level = 1) click to toggle source

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 {Vector}s 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}.

@example

h = Hamster::Hash["A" => 1, "B" => [2, 3, 4]]
h.flatten
# => Hamster::Vector["A", 1, "B", [2, 3, 4]]
h.flatten(2)
# => Hamster::Vector["A", 1, "B", 2, 3, 4]

@param level [Integer] The number of times to recursively flatten the `[key, value]` pairs in this `Hash`. @return [Vector]

# File lib/hamster/hash.rb, line 650
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) click to toggle source

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`.

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h["B"]             # => 2
h.get("B")         # => 2
h.get("Elephant")  # => nil

# Hamster Hash with a default proc:
h = Hamster::Hash.new("A" => 1, "B" => 2, "C" => 3) { |key| key.size }
h.get("B")         # => 2
h.get("Elephant")  # => 8

@param key [Object] The key to look up @return [Object]

# File lib/hamster/hash.rb, line 179
def get(key)
  entry = @trie.get(key)
  if entry
    entry[1]
  elsif @default
    @default.call(key)
  end
end
Also aliased as: []
has_key?(key)
Alias for: key?
has_value?(value)
Alias for: value?
hash() click to toggle source

See `Object#hash`. @return [Integer]

# File lib/hamster/hash.rb, line 789
def hash
  keys.to_a.sort.reduce(0) do |hash, key|
    (hash << 32) - hash + key.hash + get(key).hash
  end
end
include?(key)
Alias for: key?
inspect() click to toggle source

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.

@return [String]

# File lib/hamster/hash.rb, line 801
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() click to toggle source

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.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3, "D" => 2].invert
# => Hamster::Hash[1 => "A", 3 => "C", 2 => "B"]

@return [Hash]

# File lib/hamster/hash.rb, line 625
def invert
  pairs = []
  each { |k,v| pairs << [v, k] }
  self.class.new(pairs, &@default)
end
keep_if(&block)
Alias for: select
key(value) click to toggle source

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.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].key(2)  # => "B"

@param value [Object] The value to search for (using #==) @return [Object]

# File lib/hamster/hash.rb, line 695
def key(value)
  each { |entry| return entry[0] if value == entry[1] }
  nil
end
key?(key) click to toggle source

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.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].key?("B")  # => true

@param key [Object] The key to check for @return [Boolean]

# File lib/hamster/hash.rb, line 142
def key?(key)
  @trie.key?(key)
end
Also aliased as: has_key?, include?, member?
keys() click to toggle source

Return a new {Set} containing the keys from this `Hash`.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3, "D" => 2].keys
# => Hamster::Set["D", "C", "B", "A"]

@return [Set]

# File lib/hamster/hash.rb, line 600
def keys
  Set.alloc(@trie)
end
length()
Alias for: size
map() click to toggle source

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`.

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.map { |k, v| ["new-#{k}", v * v] }
# => Hash["new-C" => 9, "new-B" => 4, "new-A" => 1]

@yield [key, value] Once for each key/value pair. @return [Hash]

Calls superclass method
# File lib/hamster/hash.rb, line 404
def map
  return enum_for(:map) unless block_given?
  return self if empty?
  self.class.new(super, &@default)
end
Also aliased as: collect
marshal_dump() click to toggle source

@return [::Hash] @private

# File lib/hamster/hash.rb, line 864
def marshal_dump
  to_hash
end
marshal_load(dictionary) click to toggle source

@private

# File lib/hamster/hash.rb, line 869
def marshal_load(dictionary)
  @trie = Trie[dictionary]
end
member?(key)
Alias for: key?
merge(other) { |key, entry, value| ... } click to toggle source

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 a `Hamster::Hash`, a built-in Ruby `Hash`, or any `Enumerable` object which yields `[key, value]` pairs.

@example

h1 = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h2 = Hamster::Hash["C" => 70, "D" => 80]
h1.merge(h2)
# => Hamster::Hash["C" => 70, "A" => 1, "D" => 80, "B" => 2]
h1.merge(h2) { |key, v1, v2| v1 + v2 }
# => Hamster::Hash["C" => 73, "A" => 1, "D" => 80, "B" => 2]

@param other [::Enumerable] The collection to merge with @yieldparam key [Object] The key which was present in both collections @yieldparam my_value [Object] The associated value from this `Hash` @yieldparam other_value [Object] The associated value from the other collection @yieldreturn [Object] The value to associate this key with in the new `Hash` @return [Hash]

# File lib/hamster/hash.rb, line 468
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) click to toggle source

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.

@private

# File lib/hamster/hash.rb, line 818
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))) click to toggle source

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.

@example

h = Hamster::Hash["A" => 1, "B" => 2]
h.put("C", 3)
# => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.put("B") { |value| value * 10 }
# => Hamster::Hash["A" => 1, "B" => 20]

@param key [Object] The key to store @param value [Object] The value to associate it with @yield [value] The previously stored value, or `nil` if none. @yieldreturn [Object] The new value to store @return [Hash]

# File lib/hamster/hash.rb, line 260
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) click to toggle source

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.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].rassoc(2)  # => ["B", 2]

@param obj [Object] The value to search for (using #==) @return [Array]

# File lib/hamster/hash.rb, line 681
def rassoc(obj)
  each { |entry| return entry if obj == entry[1] }
  nil
end
reverse_each(&block) click to toggle source

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}.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].reverse_each { |k, v| puts "k=#{k} v=#{v}" }

k=B v=2
k=C v=3
k=A v=1
# => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]

@yield [key, value] Once for each key/value pair. @return [self]

# File lib/hamster/hash.rb, line 349
def reverse_each(&block)
  return enum_for(:reverse_each) if not block_given?
  @trie.reverse_each(&block)
  self
end
sample() click to toggle source

Return a randomly chosen `[key, value]` pair from this `Hash`. If the hash is empty, return `nil`.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].sample
# => ["C", 3]

@return [Array]

# File lib/hamster/hash.rb, line 708
def sample
  @trie.at(rand(size))
end
select(&block) click to toggle source

Return a new `Hash` with all the key/value pairs for which the block returns true.

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.select { |k, v| v >= 2 }
# => Hamster::Hash["B" => 2, "C" => 3]

@yield [key, value] Once for each key/value pair. @yieldreturn Truthy if this pair should be present in the new `Hash`. @return [Hash]

# File lib/hamster/hash.rb, line 421
def select(&block)
  return enum_for(:select) unless block_given?
  derive_new_hash(@trie.select(&block))
end
Also aliased as: find_all, keep_if
size() click to toggle source

Return the number of key/value pairs in this `Hash`.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].size  # => 3

@return [Integer]

# File lib/hamster/hash.rb, line 121
def size
  @trie.size
end
Also aliased as: length
slice(*wanted) click to toggle source

Return a new `Hash` with only the associations for the `wanted` keys retained.

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.slice("B", "C")  # => Hamster::Hash["B" => 2, "C" => 3]

@param wanted [::Enumerable] The keys to retain @return [Hash]

# File lib/hamster/hash.rb, line 555
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() click to toggle source

Return a sorted {Vector} which contains all the `[key, value]` pairs in this `Hash` as two-element `Array`s.

@overload sort

Uses `#<=>` to determine sorted order.

@overload sort { |(k1, v1), (k2, v2)| … }

Uses the block as a comparator to determine sorted order.

@example
  h = Hamster::Hash["Dog" => 1, "Elephant" => 2, "Lion" => 3]
  h.sort { |(k1, v1), (k2, v2)| k1.size  <=> k2.size }
  # => Hamster::Vector[["Dog", 1], ["Lion", 3], ["Elephant", 2]]
@yield [(k1, v1), (k2, v2)] Any number of times with different pairs of key/value associations.
@yieldreturn [Integer] Negative if the first pair should be sorted
                       lower, positive if the latter pair, or 0 if equal.

@see ::Enumerable#sort

@return [Vector]

Calls superclass method
# File lib/hamster/hash.rb, line 512
def sort
  Vector.new(super)
end
sort_by() click to toggle source

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 `#<=>`.

@see ::Enumerable#sort_by

@example

h = Hamster::Hash["Dog" => 1, "Elephant" => 2, "Lion" => 3]
h.sort_by { |key, value| key.size }
# => Hamster::Vector[["Dog", 1], ["Lion", 3], ["Elephant", 2]]

@yield [key, value] Once for each key/value pair. @yieldreturn a sort key object for the yielded pair. @return [Vector]

Calls superclass method Hamster::Enumerable#sort_by
# File lib/hamster/hash.rb, line 531
def sort_by
  Vector.new(super)
end
store(key, value) click to toggle source

An alias for {#put} to match RubyHash's API. Does not support {#put}'s block form.

@see put @param key [Object] The key to store @param value [Object] The value to associate it with @return [Hash]

# File lib/hamster/hash.rb, line 298
def store(key, value)
  put(key, value)
end
to_h()
Alias for: to_hash
to_hash() click to toggle source

Convert this `Hamster::Hash` to an instance of Ruby's built-in `Hash`.

@return [::Hash]

# File lib/hamster/hash.rb, line 837
def to_hash
  output = {}
  each do |key, value|
    output[key] = value
  end
  output
end
Also aliased as: to_h
to_proc() click to toggle source

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 result of the default proc).

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.to_proc.call("B")
# => 2
["A", "C", "X"].map(&h)   # The & is short for .to_proc in Ruby
# => [1, 3, nil]

@return [Proc]

# File lib/hamster/hash.rb, line 858
def to_proc
  lambda { |key| get(key) }
end
value?(value) click to toggle source

Return `true` if this `Hash` has one or more keys which map to the provided value.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3].value?(2)  # => true

@param value [Object] The value to check for @return [Boolean]

# File lib/hamster/hash.rb, line 156
def value?(value)
  each { |k,v| return true if value == v }
  false
end
Also aliased as: has_value?
values() click to toggle source

Return a new {Vector} populated with the values from this `Hash`.

@example

Hamster::Hash["A" => 1, "B" => 2, "C" => 3, "D" => 2].values
# => Hamster::Vector[2, 3, 2, 1]

@return [Vector]

# File lib/hamster/hash.rb, line 611
def values
  Vector.new(each_value.to_a.freeze)
end
values_at(*wanted) click to toggle source

Return a {Vector} of the values which correspond to the `wanted` keys. If any of the `wanted` keys are not present in this `Hash`, `nil` will be placed instead, or the result of the default proc (if one is defined), similar to the behavior of {#get}.

@example

h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
h.values_at("B", "A", "D")  # => Hamster::Vector[2, 1, nil]

@param wanted [Array] The keys to retrieve @return [Vector]

# File lib/hamster/hash.rb, line 572
def values_at(*wanted)
  array = wanted.map { |key| get(key) }
  Vector.new(array.freeze)
end

Private Instance Methods

derive_new_hash(trie) click to toggle source

Return a new `Hash` which is derived from this one, using a modified {Trie}. The new `Hash` will retain the existing default block, if there is one.

# File lib/hamster/hash.rb, line 878
def derive_new_hash(trie)
  if trie.equal?(@trie)
    self
  elsif trie.empty?
    if @default
      self.class.alloc(EmptyTrie, @default)
    else
      self.class.empty
    end
  else
    self.class.alloc(trie, @default)
  end
end