Hash(K, V) - Crystal 1.20.1

# class Hash(K, V)

- Hash(K, V)
- Reference
- Object

##
Overview

A `Hash` represents a collection of key-value mappings, similar to a dictionary.

Main operations are storing a key-value mapping (`#[]=`) and querying the value associated to a key (`#[]`). Key-value mappings can also be deleted (`#delete`). Keys are unique within a hash. When adding a key-value mapping with a key that is already in use, the old value will be forgotten.

    # Create a new Hash for mapping String to Int32
    hash = Hash(String, Int32).new
    hash["one"] = 1
    hash["two"] = 2
    hash["one"] # => 1

Hash literals can also be used to create a `Hash`:

    {"one" => 1, "two" => 2}

Implementation is based on an open hash table. Two objects refer to the same hash key when their hash value (`Object#hash`) is identical and both objects are equal to each other (`Object#==`).

Enumeration follows the order that the corresponding keys were inserted.

NOTE When using mutable data types as keys, changing the value of a key after it was inserted into the `Hash` may lead to undefined behaviour. This can be restored by re-indexing the hash with `#rehash`.

##
Included Modules

- Enumerable({K, V})
- Iterable({K, V})

##
Defined in:

hash.cr
json/any.cr
json/to_json.cr
yaml/any.cr
yaml/to_yaml.cr

##
Constructors

- .new(default_value : V, initial_capacity = nil)

  Creates a new empty `Hash` where the default_value is returned if a key is missing.

- .new(ctx : YAML::ParseContext, node : YAML::Nodes::Node)
- .new(pull : JSON::PullParser)

  Reads a Hash from the given pull parser.

- .new

  Creates a new empty `Hash`.

- .new(block : Hash(K, V), K -> V | Nil = nil, *, initial_capacity = nil)

  Creates a new empty `Hash` with a block for handling missing keys.

- .new(ctx : YAML::ParseContext, node : YAML::Nodes::Node, &)
- .new(initial_capacity = nil, &block : Hash(K, V), K -> V)

  Creates a new empty `Hash` with a block that handles missing keys.

##
Class Method Summary

- .zip(ary1 : Array(K), ary2 : Array(V))

  Zips two arrays into a `Hash`, taking keys from ary1 and values from ary2.

##
Instance Method Summary

- #==(other : Hash) : Bool

  Compares with other.

- #==(other : JSON::Any)
- #==(other : YAML::Any)
- #[](key)

  Returns the value for the key given by key.

- #[]=(key : K, value : V) : V

  Sets the value of key to the given value.

- #[]?(key)

  Returns the value for the key given by key.

- #clear : self

  Empties a `Hash` and returns it.

- #clone : Hash(K, V)

  Similar to `#dup`, but duplicates the values as well.

- #compact

  Returns new `Hash` without `nil` values.

- #compact! : self

  Removes all `nil` value from `self`.

- #compare_by_identity : self

  Makes this hash compare keys using their object identity (`object_id)` for types that define such method (`Reference` types, but also structs that might wrap other `Reference` types and delegate the `object_id` method to them).

- #compare_by_identity? : Bool

  Returns `true` if this Hash is comparing keys by `object_id`.

- #delete(key) : V | Nil

  Deletes the key-value pair and returns the value, otherwise returns `nil`.

- #delete(key, &)

  Deletes the key-value pair and returns the value, else yields key with given block.

- #dig(key : K, *subkeys)

  Traverses the depth of a structure and returns the value, otherwise raises `KeyError`.

- #dig?(key : K, *subkeys)

  Traverses the depth of a structure and returns the value.

- #dup : Hash(K, V)

  Duplicates a `Hash`.

- #each(& : Tuple(K, V) -> ) : Nil

  Calls the given block for each key-value pair and passes in the key and the value.

- #each

  Returns an iterator over the hash entries.

- #each_key(& : K -> )

  Calls the given block for each key-value pair and passes in the key.

- #each_key

  Returns an iterator over the hash keys.

- #each_value(& : V -> )

  Calls the given block for each key-value pair and passes in the value.

- #each_value

  Returns an iterator over the hash values.

- #empty? : Bool

  Returns `true` when hash contains no key-value pairs.

- #fetch(key, default)

  Returns the value for the key given by key, or when not found the value given by default.

- #fetch(key, &)

  Returns the value for the key given by key, or when not found calls the given block with the key.

- #first_key : K

  Returns the first key in the hash.

- #first_key? : K | Nil

  Returns the first key if it exists, or returns `nil`.

- #first_value : V

  Returns the first value in the hash.

- #first_value? : V | Nil

  Returns the first value if it exists, or returns `nil`.

- #has_key?(key) : Bool

  Returns `true` when key given by key exists, otherwise `false`.

- #has_value?(val) : Bool

  Returns `true` when value given by value exists, otherwise `false`.

- #hash(hasher)

  See `Object#hash(hasher)`

- #inspect(io : IO) : Nil

  Appends a String representation of this object which includes its class name, its object address and the values of all instance variables.

- #invert : Hash(V, K)

  Inverts keys and values.

- #key_for(value) : K

  Returns a key with the given value, else raises `KeyError`.

- #key_for(value, &)

  Returns a key with the given value, else yields value with the given block.

- #key_for?(value) : K | Nil

  Returns a key with the given value, else `nil`.

- #keys : Array(K)

  Returns a new `Array` with all the keys.

- #last_key : K

  Returns the last key in the hash.

- #last_key? : K | Nil

  Returns the last key if it exists, or returns `nil`.

- #last_value : V

  Returns the last value in the hash.

- #last_value? : V | Nil

  Returns the last value if it exists, or returns `nil`.

- #merge(other : Hash(L, W)) : Hash(K | L, V | W) forall L, W

  Returns a new `Hash` with the keys and values of this hash and other combined.

- #merge(other : Hash(L, W), & : L, V, W -> V | W) : Hash(K | L, V | W) forall L, W
- #merge!(other : Hash) : self

  Similar to `#merge`, but the receiver is modified.

- #merge!(other : Hash, &) : self

  Adds the contents of other to this hash.

- #pretty_print(pp) : Nil
- #proper_subset_of?(other : Hash) : Bool

  Returns `true` if `self` is a subset of other.

- #proper_superset_of?(other : Hash) : Bool

  Returns `true` if other is a subset of `self` or equals to `self`.

- #put(key : K, value : V, &)

  Sets the value of key to the given value.

- #put_if_absent(key : K, value : V) : V

  Sets the value of key to the given value, unless a value for key already exists.

- #put_if_absent(key : K, & : K -> V) : V

  Sets the value of key to the value returned by the given block, unless a value for key already exists.

- #rehash : Nil

  Rebuilds the hash table based on the current keys.

- #reject(& : K, V -> ) : Hash(K, V)

  Returns a new hash consisting of entries for which the block is falsey.

- #reject(keys : Enumerable) : Hash(K, V)

  Returns a new `Hash` without the given keys.

- #reject(*keys) : Hash(K, V)

  Returns a new `Hash` without the given keys.

- #reject!(& : K, V -> _)

  Equivalent to `Hash#reject`, but makes modification on the current object rather than returning a new one.

- #reject!(keys : Enumerable) : self

  Removes a list of keys out of hash.

- #reject!(*keys) : self

  Removes a list of keys out of hash.

- #select(& : K, V -> ) : Hash(K, V)

  Returns a new hash consisting of entries for which the block is truthy.

- #select(keys : Enumerable) : Hash(K, V)

  Returns a new `Hash` with the given keys.

- #select(*keys) : Hash(K, V)

  Returns a new `Hash` with the given keys.

- #select!(& : K, V -> ) : self

  Equivalent to `Hash#select` but makes modification on the current object rather than returning a new one.

- #select!(keys : Indexable) : self

  Removes every element except the given ones.

- #select!(keys : Enumerable) : self

  Removes every element except the given ones.

- #select!(*keys) : self

  Removes every element except the given ones.

- #shift : Tuple(K, V)

  Deletes and returns the first key-value pair in the hash, or raises `IndexError` if the hash is empty.

- #shift(&)

  Deletes and returns the first key-value pair in the hash.

- #shift? : Tuple(K, V) | Nil

  Same as `#shift`, but returns `nil` if the hash is empty.

- #size : Int32

  Returns the number of elements in this Hash.

- #subset_of?(other : Hash) : Bool

  Returns `true` if `self` is a subset of other or equals to other.

- #superset_of?(other : Hash) : Bool

  Returns `true` if other is a subset of `self`.

- #to_a : Array(Tuple(K, V))

  Returns an `Array` of `Tuple(K, V)` with key and values belonging to this Hash.

- #to_a(&block : Tuple(K, V) -> U) : Array(U) forall U

  Returns an `Array` with the results of running block against tuples with key and values belonging to this Hash.

- #to_h : self

  Returns `self`.

- #to_json(json : JSON::Builder) : Nil

  Serializes this Hash into JSON.

- #to_s(io : IO) : Nil

  Converts to a `String`.

- #to_yaml(yaml : YAML::Nodes::Builder) : Nil
- #transform_keys(& : K, V -> K2) : Hash(K2, V) forall K2

  Returns a new hash with all keys converted using the block operation.

- #transform_keys!(& : K, V -> K) : self

  Destructively transforms all keys using a block.

- #transform_values(& : V, K -> V2) : Hash(K, V2) forall V2

  Returns a new hash with the results of running block once for every value.

- #transform_values!(& : V, K -> V) : self

  Destructively transforms all values using a block.

- #update(key : K, & : V -> V) : V

  Updates the current value of key with the value returned by the given block (the current value is used as input for the block).

- #values : Array(V)

  Returns only the values as an `Array`.

- #values_at(*keys : K)

  Returns a tuple populated with the values of the given keys, with the same order.

### Instance methods inherited from module `Iterable({K, V})`

chunk(reuse = false, &block : {K, V} -> U) forall U chunk, chunk_while(reuse : Bool | Array({K, V}) = false, &block : {K, V}, {K, V} -> B) forall B chunk_while, cycle(n)
cycle cycle, each each, each_cons(count : Int, reuse = false) each_cons, each_cons_pair each_cons_pair, each_slice(count : Int, reuse = false) each_slice, each_step(n : Int)
each_step(n : Int, *, offset : Int) each_step, each_with_index(offset = 0) each_with_index, each_with_object(obj) each_with_object, slice_after(reuse : Bool | Array({K, V}) = false, &block : {K, V} -> B) forall B
slice_after(pattern, reuse : Bool | Array({K, V}) = false) slice_after, slice_before(reuse : Bool | Array({K, V}) = false, &block : {K, V} -> B) forall B
slice_before(pattern, reuse : Bool | Array({K, V}) = false) slice_before, slice_when(reuse : Bool | Array({K, V}) = false, &block : {K, V}, {K, V} -> B) forall B slice_when

### Instance methods inherited from module `Enumerable({K, V})`

accumulate(initial : U) : Array(U) forall U
accumulate : Array({K, V})
accumulate(initial : U, &block : U, {K, V} -> U) : Array(U) forall U
accumulate(&block : {K, V}, {K, V} -> {K, V}) : Array({K, V}) accumulate, all?(& : {K, V} -> ) : Bool
all?(pattern) : Bool
all? : Bool all?, any?(& : {K, V} -> ) : Bool
any?(pattern) : Bool
any? : Bool any?, chunks(&block : {K, V} -> U) forall U chunks, compact_map(& : {K, V} -> _) compact_map, count(& : {K, V} -> ) : Int32
count(item) : Int32 count, cycle(n, & : {K, V} -> ) : Nil
cycle(& : {K, V} -> ) : Nil cycle, each(& : {K, V} -> ) each, each_cons(count : Int, reuse = false, &) each_cons, each_cons_pair(& : {K, V}, {K, V} -> ) : Nil each_cons_pair, each_slice(count : Int, reuse = false, &) each_slice, each_step(n : Int, *, offset : Int = 0, & : {K, V} -> ) : Nil each_step, each_with_index(offset = 0, &) each_with_index, each_with_object(obj : U, & : {K, V}, U -> ) : U forall U each_with_object, empty? : Bool empty?, find(if_none = nil, & : {K, V} -> ) find, find!(& : {K, V} -> ) : {K, V} find!, find_value(if_none = nil, & : {K, V} -> ) find_value, first(&)
first(count : Int) : Array({K, V})
first : {K, V} first, first? : {K, V} | Nil first?, flat_map(& : {K, V} -> _) flat_map, group_by(& : {K, V} -> U) forall U group_by, in_groups_of(size : Int, filled_up_with : U = nil) forall U
in_groups_of(size : Int, filled_up_with : U = nil, reuse = false, &) forall U in_groups_of, in_slices_of(size : Int) : Array(Array({K, V})) in_slices_of, includes?(obj) : Bool includes?, index(& : {K, V} -> ) : Int32 | Nil
index(obj) : Int32 | Nil index, index!(& : {K, V} -> ) : Int32
index!(obj) : Int32 index!, index_by(& : {K, V} -> U) : Hash(U, {K, V}) forall U index_by, join(io : IO, separator = "") : Nil
join(separator, io : IO) : Nil
join(separator = "") : String
join(io : IO, separator = "", & : {K, V}, IO -> )
join(separator, io : IO, &)
join(separator = "", & : {K, V} -> ) join, map(& : {K, V} -> U) : Array(U) forall U map, map_with_index(offset = 0, & : {K, V}, Int32 -> U) : Array(U) forall U map_with_index, max(count : Int) : Array({K, V})
max : {K, V} max, max? : {K, V} | Nil max?, max_by(& : {K, V} -> U) : {K, V} forall U max_by, max_by?(& : {K, V} -> U) : {K, V} | Nil forall U max_by?, max_of(& : {K, V} -> U) : U forall U max_of, max_of?(& : {K, V} -> U) : U | Nil forall U max_of?, min(count : Int) : Array({K, V})
min : {K, V} min, min? : {K, V} | Nil min?, min_by(& : {K, V} -> U) : {K, V} forall U min_by, min_by?(& : {K, V} -> U) : {K, V} | Nil forall U min_by?, min_of(& : {K, V} -> U) : U forall U min_of, min_of?(& : {K, V} -> U) : U | Nil forall U min_of?, minmax : Tuple({K, V}, {K, V}) minmax, minmax? : Tuple({K, V} | Nil, {K, V} | Nil) minmax?, minmax_by(& : {K, V} -> U) : Tuple({K, V}, {K, V}) forall U minmax_by, minmax_by?(& : {K, V} -> U) : Tuple({K, V}, {K, V}) | Tuple(Nil, Nil) forall U minmax_by?, minmax_of(& : {K, V} -> U) : Tuple(U, U) forall U minmax_of, minmax_of?(& : {K, V} -> U) : Tuple(U, U) | Tuple(Nil, Nil) forall U minmax_of?, none?(& : {K, V} -> ) : Bool
none?(pattern) : Bool
none? : Bool none?, one?(& : {K, V} -> ) : Bool
one?(pattern) : Bool
one? : Bool one?, partition(& : {K, V} -> ) : Tuple(Array({K, V}), Array({K, V}))
partition(type : U.class) forall U partition, present? : Bool present?, product(initial : Number)
product
product(initial : Number, & : {K, V} -> )
product(& : {K, V} -> _) product, reduce(memo, &)
reduce(&) reduce, reduce?(&) reduce?, reject(& : {K, V} -> )
reject(type : U.class) forall U
reject(pattern) : Array({K, V}) reject, sample(n : Int, random : Random | Nil = nil) : Array({K, V})
sample(random : Random | Nil = nil) : {K, V} sample, select(& : {K, V} -> )
select(type : U.class) : Array(U) forall U
select(pattern) : Array({K, V}) select, size : Int32 size, skip(count : Int) skip, skip_while(& : {K, V} -> ) : Array({K, V}) skip_while, sum(initial)
sum
sum(initial, & : {K, V} -> )
sum(& : {K, V} -> ) sum, take_while(& : {K, V} -> ) : Array({K, V}) take_while, tally(hash)
tally : Hash({K, V}, Int32) tally, tally_by(hash, &)
tally_by(&block : {K, V} -> U) : Hash(U, Int32) forall U tally_by, to_a : Array({K, V})
to_a(& : {K, V} -> U) : Array(U) forall U to_a, to_h
to_h(& : {K, V} -> Tuple(K, V)) forall K, V to_h, to_set : Set({K, V})
to_set(&block : {K, V} -> U) : Set(U) forall U to_set, zip(*others : Indexable | Iterable | Iterator, &)
zip(*others : Indexable | Iterable | Iterator) zip, zip?(*others : Indexable | Iterable | Iterator, &)
zip?(*others : Indexable | Iterable | Iterator) zip?

### Class methods inherited from module `Enumerable({K, V})`

element_type(x) element_type

### Instance methods inherited from class `Reference`

==(other : self)
==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s

### Constructor methods inherited from class `Reference`

new new, unsafe_construct(address : Pointer, *args, **opts) : self unsafe_construct

### Class methods inherited from class `Reference`

pre_initialize(address : Pointer) pre_initialize

### Instance methods inherited from class `Object`

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

### Class methods inherited from class `Object`

from_json(string_or_io : String | IO, root : String)
from_json(string_or_io : String | IO) from_json, from_yaml(string_or_io : String | IO) from_yaml

### Macros inherited from class `Object`

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

##
Constructor Detail

def self.new(default_value : V, initial_capacity = nil) #

Creates a new empty `Hash` where the default_value is returned if a key is missing.

    inventory = Hash(String, Int32).new(0)
    inventory["socks"] = 3
    inventory["pickles"] # => 0

WARNING When the default value gets returned on a missing key, it is not stored into the hash under that key. If you want that behaviour, please use the overload with a block.

WARNING The default value is returned as-is. It gets neither duplicated nor cloned. For types with reference semantics this means it will be exactly the same object every time.

    hash = Hash(String, Array(Int32)).new([1])
    hash["a"][0] = 2
    hash["b"] # => [2]

- `.new(&block : (Hash(K, V), K -> V))` is an alternative with a block that can return a different default value for each invocation.

The initial_capacity is useful to avoid unnecessary reallocations of the internal buffer in case of growth. If the number of elements a hash will hold is known, the hash should be initialized with that capacity for improved performance. Otherwise, the default is 8. Inputs lower than 8 are ignored.

def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) #
def self.new(pull : JSON::PullParser) #

Reads a Hash from the given pull parser.

Keys are read by invoking `from_json_object_key?` on this hash's key type (`K`), which must return a value of type `K` or `nil`. If `nil` is returned a `JSON::ParseException` is raised.

Values are parsed using the regular `.new(pull : JSON::PullParser)` method.

def self.new #

Creates a new empty `Hash`.

def self.new(block : Hash(K, V), K -> V | Nil = nil, *, initial_capacity = nil) #

Creates a new empty `Hash` with a block for handling missing keys.

    proc = ->(hash : Hash(String, Int32), key : String) { hash[key] = key.size }
    hash = Hash(String, Int32).new(proc)

    hash.size   # => 0
    hash["foo"] # => 3
    hash.size   # => 1
    hash["bar"] = 10
    hash["bar"] # => 10

The initial_capacity is useful to avoid unnecessary reallocations of the internal buffer in case of growth. If the number of elements a hash will hold is known, the hash should be initialized with that capacity for improved performance. Otherwise, the default is 8. Inputs lower than 8 are ignored.

def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node, &) #
def self.new(initial_capacity = nil, &block : Hash(K, V), K -> V) #

Creates a new empty `Hash` with a block that handles missing keys.

    hash = Hash(String, String).new do |hash, key|
      "some default value"
    end

    hash.size           # => 0
    hash["foo"] = "bar" # => "bar"
    hash.size           # => 1
    hash["baz"]         # => "some default value"
    hash.size           # => 1
    hash                # => {"foo" => "bar"}

WARNING When the default block is invoked on a missing key, its return value is not implicitly stored into the hash under that key. If you want that behaviour, you need to store it explicitly:

    hash = Hash(String, Int32).new do |hash, key|
      hash[key] = key.size
    end

    hash.size   # => 0
    hash["foo"] # => 3
    hash.size   # => 1
    hash["bar"] = 10
    hash["bar"] # => 10

The initial_capacity is useful to avoid unnecessary reallocations of the internal buffer in case of growth. If the number of elements a hash will hold is known, the hash should be initialized with that capacity for improved performance. Otherwise, the default is 8. Inputs lower than 8 are ignored.

##
Class Method Detail

def self.zip(ary1 : Array(K), ary2 : Array(V)) #

Zips two arrays into a `Hash`, taking keys from ary1 and values from ary2.

    Hash.zip(["key1", "key2", "key3"], ["value1", "value2", "value3"])
    # => {"key1" => "value1", "key2" => "value2", "key3" => "value3"}

##
Instance Method Detail

def ==(other : Hash) : Bool #

Compares with other. Returns `true` if all key-value pairs are the same.

def ==(other : JSON::Any) #
def ==(other : YAML::Any) #
def [](key) #

Returns the value for the key given by key. If not found, returns the default value given by `Hash.new`, otherwise raises `KeyError`.

    h = {"foo" => "bar"}
    h["foo"] # => "bar"

    h = Hash(String, String).new("bar")
    h["foo"] # => "bar"

    h = Hash(String, String).new { "bar" }
    h["foo"] # => "bar"

    h = Hash(String, String).new
    h["foo"] # raises KeyError

def []=(key : K, value : V) : V #

Sets the value of key to the given value.

    h = {} of String => String
    h["foo"] = "bar"
    h["foo"] # => "bar"

def []?(key) #

Returns the value for the key given by key. If not found, returns `nil`. This ignores the default value set by `Hash.new`.

    h = {"foo" => "bar"}
    h["foo"]? # => "bar"
    h["bar"]? # => nil

    h = Hash(String, String).new("bar")
    h["foo"]? # => nil

def clear : self #

Empties a `Hash` and returns it.

    hash = {"foo" => "bar"}
    hash.clear # => {}

def clone : Hash(K, V) #

Similar to `#dup`, but duplicates the values as well.

    hash_a = {"foobar" => {"foo" => "bar"}}
    hash_b = hash_a.clone
    hash_b["foobar"]["foo"] = "baz"
    hash_a # => {"foobar" => {"foo" => "bar"}}

def compact #

Returns new `Hash` without `nil` values.

    hash = {"hello" => "world", "foo" => nil}
    hash.compact # => {"hello" => "world"}

def compact! : self #

Removes all `nil` value from `self`. Returns `self`.

    hash = {"hello" => "world", "foo" => nil}
    hash.compact! # => {"hello" => "world"}

def compare_by_identity : self #

Makes this hash compare keys using their object identity (`object_id)` for types that define such method (`Reference` types, but also structs that might wrap other `Reference` types and delegate the `object_id` method to them).

    h1 = {"foo" => 1, "bar" => 2}
    h1["fo" + "o"]? # => 1

    h1.compare_by_identity
    h1.compare_by_identity? # => true
    h1["fo" + "o"]?         # => nil # not the same String instance

def compare_by_identity? : Bool #

Returns `true` if this Hash is comparing keys by `object_id`.

See `#compare_by_identity`.

def delete(key) : V | Nil #

Deletes the key-value pair and returns the value, otherwise returns `nil`.

    h = {"foo" => "bar"}
    h.delete("foo")     # => "bar"
    h.fetch("foo", nil) # => nil

def delete(key, &) #

Deletes the key-value pair and returns the value, else yields key with given block.

    h = {"foo" => "bar"}
    h.delete("foo") { |key| "#{key} not found" } # => "bar"
    h.fetch("foo", nil)                          # => nil
    h.delete("baz") { |key| "#{key} not found" } # => "baz not found"

def dig(key : K, *subkeys) #

Traverses the depth of a structure and returns the value, otherwise raises `KeyError`.

    h = {"a" => {"b" => [10, 20, 30]}}
    h.dig "a", "b" # => [10, 20, 30]
    h.dig "a", "x" # raises KeyError

def dig?(key : K, *subkeys) #

Traverses the depth of a structure and returns the value. Returns `nil` if not found.

    h = {"a" => {"b" => [10, 20, 30]}}
    h.dig? "a", "b" # => [10, 20, 30]
    h.dig? "a", "x" # => nil

def dup : Hash(K, V) #

Duplicates a `Hash`.

    hash_a = {"foo" => "bar"}
    hash_b = hash_a.dup
    hash_b.merge!({"baz" => "qux"})
    hash_a # => {"foo" => "bar"}

def each(& : Tuple(K, V) -> ) : Nil #

Calls the given block for each key-value pair and passes in the key and the value.

    h = {"foo" => "bar"}

    h.each do |key, value|
      key   # => "foo"
      value # => "bar"
    end

    h.each do |key_and_value|
      key_and_value # => {"foo", "bar"}
    end

The enumeration follows the order the keys were inserted.

def each #

Returns an iterator over the hash entries. Which behaves like an `Iterator` returning a `Tuple` consisting of the key and value types.

    hsh = {"foo" => "bar", "baz" => "qux"}
    iterator = hsh.each

    iterator.next # => {"foo", "bar"}
    iterator.next # => {"baz", "qux"}

The enumeration follows the order the keys were inserted.

def each_key(& : K -> ) #

Calls the given block for each key-value pair and passes in the key.

    h = {"foo" => "bar"}
    h.each_key do |key|
      key # => "foo"
    end

The enumeration follows the order the keys were inserted.

def each_key #

Returns an iterator over the hash keys. Which behaves like an `Iterator` consisting of the key's types.

    hsh = {"foo" => "bar", "baz" => "qux"}
    iterator = hsh.each_key

    key = iterator.next
    key # => "foo"

    key = iterator.next
    key # => "baz"

The enumeration follows the order the keys were inserted.

def each_value(& : V -> ) #

Calls the given block for each key-value pair and passes in the value.

    h = {"foo" => "bar"}
    h.each_value do |value|
      value # => "bar"
    end

The enumeration follows the order the keys were inserted.

def each_value #

Returns an iterator over the hash values. Which behaves like an `Iterator` consisting of the value's types.

    hsh = {"foo" => "bar", "baz" => "qux"}
    iterator = hsh.each_value

    value = iterator.next
    value # => "bar"

    value = iterator.next
    value # => "qux"

The enumeration follows the order the keys were inserted.

def empty? : Bool #

Returns `true` when hash contains no key-value pairs.

    h = Hash(String, String).new
    h.empty? # => true

    h = {"foo" => "bar"}
    h.empty? # => false

def fetch(key, default) #

Returns the value for the key given by key, or when not found the value given by default. This ignores the default value set by `Hash.new`.

    h = {"foo" => "bar"}
    h.fetch("foo", "foo") # => "bar"
    h.fetch("bar", "foo") # => "foo"

def fetch(key, &) #

Returns the value for the key given by key, or when not found calls the given block with the key.

    h = {"foo" => "bar"}
    h.fetch("foo") { "default value" }  # => "bar"
    h.fetch("bar") { "default value" }  # => "default value"
    h.fetch("bar") { |key| key.upcase } # => "BAR"

def first_key : K #

Returns the first key in the hash.

def first_key? : K | Nil #

Returns the first key if it exists, or returns `nil`.

    hash = {"foo1" => "bar1", "foz2" => "baz2"}
    hash.first_key? # => "foo1"
    hash.clear
    hash.first_key? # => nil

def first_value : V #

Returns the first value in the hash.

def first_value? : V | Nil #

Returns the first value if it exists, or returns `nil`.

    hash = {"foo1" => "bar1", "foz2" => "baz2"}
    hash.first_value? # => "bar1"
    hash.clear
    hash.first_value? # => nil

def has_key?(key) : Bool #

Returns `true` when key given by key exists, otherwise `false`.

    h = {"foo" => "bar"}
    h.has_key?("foo") # => true
    h.has_key?("bar") # => false

def has_value?(val) : Bool #

Returns `true` when value given by value exists, otherwise `false`.

    h = {"foo" => "bar"}
    h.has_value?("foo") # => false
    h.has_value?("bar") # => true

def hash(hasher) #

See `Object#hash(hasher)`

def inspect(io : IO) : Nil #
Description copied from class Reference

Appends a String representation of this object which includes its class name, its object address and the values of all instance variables.

    class Person
      def initialize(@name : String, @age : Int32)
      end
    end

    Person.new("John", 32).inspect # => #<Person:0x10fd31f20 @name="John", @age=32>

def invert : Hash(V, K) #

Inverts keys and values. If there are duplicated values, the last key becomes the new value.

    {"foo" => "bar"}.invert                 # => {"bar" => "foo"}
    {"foo" => "bar", "baz" => "bar"}.invert # => {"bar" => "baz"}

def key_for(value) : K #

Returns a key with the given value, else raises `KeyError`.

    hash = {"foo" => "bar", "baz" => "qux"}
    hash.key_for("bar")    # => "foo"
    hash.key_for("qux")    # => "baz"
    hash.key_for("foobar") # raises KeyError (Missing hash key for value: foobar)

def key_for(value, &) #

Returns a key with the given value, else yields value with the given block.

    hash = {"foo" => "bar"}
    hash.key_for("bar") { |value| value.upcase } # => "foo"
    hash.key_for("qux") { |value| value.upcase } # => "QUX"

def key_for?(value) : K | Nil #

Returns a key with the given value, else `nil`.

    hash = {"foo" => "bar", "baz" => "qux"}
    hash.key_for?("bar")    # => "foo"
    hash.key_for?("qux")    # => "baz"
    hash.key_for?("foobar") # => nil

def keys : Array(K) #

Returns a new `Array` with all the keys.

    h = {"foo" => "bar", "baz" => "bar"}
    h.keys # => ["foo", "baz"]

def last_key : K #

Returns the last key in the hash.

def last_key? : K | Nil #

Returns the last key if it exists, or returns `nil`.

    hash = {"foo1" => "bar1", "foz2" => "baz2"}
    hash.last_key? # => "foz2"
    hash.clear
    hash.last_key? # => nil

def last_value : V #

Returns the last value in the hash.

def last_value? : V | Nil #

Returns the last value if it exists, or returns `nil`.

    hash = {"foo1" => "bar1", "foz2" => "baz2"}
    hash.last_value? # => "baz2"
    hash.clear
    hash.last_value? # => nil

def merge(other : Hash(L, W)) : Hash(K | L, V | W) forall L, W #

Returns a new `Hash` with the keys and values of this hash and other combined. A value in other takes precedence over the one in this hash.

    hash = {"foo" => "bar"}
    hash.merge({"baz" => "qux"})
    # => {"foo" => "bar", "baz" => "qux"}
    hash
    # => {"foo" => "bar"}

def merge(other : Hash(L, W), & : L, V, W -> V | W) : Hash(K | L, V | W) forall L, W #
def merge!(other : Hash) : self #

Similar to `#merge`, but the receiver is modified.

    hash = {"foo" => "bar"}
    hash.merge!({"baz" => "qux"})
    hash # => {"foo" => "bar", "baz" => "qux"}

def merge!(other : Hash, &) : self #

Adds the contents of other to this hash. If a key exists in both hashes, the given block is called to determine the value to be used. The block arguments are the key, the value in `self` and the value in other.

    hash = {"a" => 100, "b" => 200}
    other = {"b" => 254, "c" => 300}
    hash.merge!(other) { |key, v1, v2| v1 + v2 }
    hash # => {"a" => 100, "b" => 454, "c" => 300}

def pretty_print(pp) : Nil #
def proper_subset_of?(other : Hash) : Bool #

Returns `true` if `self` is a subset of other.

def proper_superset_of?(other : Hash) : Bool #

Returns `true` if other is a subset of `self` or equals to `self`.

def put(key : K, value : V, &) #

Sets the value of key to the given value.

If a value already exists for key, that (old) value is returned. Otherwise the given block is invoked with key and its value is returned.

    h = {} of Int32 => String
    h.put(1, "one") { "didn't exist" } # => "didn't exist"
    h.put(1, "uno") { "didn't exist" } # => "one"
    h.put(2, "two") { |key| key.to_s } # => "2"
    h                                  # => {1 => "one", 2 => "two"}

def put_if_absent(key : K, value : V) : V #

Sets the value of key to the given value, unless a value for key already exists.

If a value already exists for key, that (old) value is returned. Otherwise value is returned.

    h = {} of Int32 => String
    h.put_if_absent(1, "one") # => "one"
    h.put_if_absent(1, "uno") # => "one"
    h.put_if_absent(2, "two") # => "two"
    h                         # => {1 => "one", 2 => "two"}

def put_if_absent(key : K, & : K -> V) : V #

Sets the value of key to the value returned by the given block, unless a value for key already exists.

If a value already exists for key, that (old) value is returned. Otherwise the given block is invoked with key and its value is returned.

    h = {} of Int32 => Array(String)
    h.put_if_absent(1) { |key| [key.to_s] } # => ["1"]
    h.put_if_absent(1) { [] of String }     # => ["1"]
    h.put_if_absent(2) { |key| [key.to_s] } # => ["2"]
    h                                       # => {1 => ["1"], 2 => ["2"]}

`hash.put_if_absent(key) { value }` is a more performant alternative to `hash[key] ||= value` that also works correctly when the hash may contain falsey values.

def rehash : Nil #

Rebuilds the hash table based on the current keys.

When using mutable data types as keys, modifying a key after it was inserted into the `Hash` may lead to undefined behaviour. This method re-indexes the hash using the current keys.

def reject(& : K, V -> ) : Hash(K, V) #

Returns a new hash consisting of entries for which the block is falsey.

    h = {"a" => 100, "b" => 200, "c" => 300}
    h.reject { |k, v| k > "a" } # => {"a" => 100}
    h.reject { |k, v| v < 200 } # => {"b" => 200, "c" => 300}

def reject(keys : Enumerable) : Hash(K, V) #

Returns a new `Hash` without the given keys.

    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.reject(["a", "c"]) # => {"b" => 2, "d" => 4}

def reject(*keys) : Hash(K, V) #

Returns a new `Hash` without the given keys.

    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.reject("a", "c") # => {"b" => 2, "d" => 4}

def reject!(& : K, V -> _) #

Equivalent to `Hash#reject`, but makes modification on the current object rather than returning a new one. Returns `self`.

def reject!(keys : Enumerable) : self #

Removes a list of keys out of hash.

    hash = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}
    hash.reject!(["a", "c"]) # => {"b" => 2, "d" => 4}
    hash                     # => {"b" => 2, "d" => 4}

def reject!(*keys) : self #

Removes a list of keys out of hash.

    hash = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}
    hash.reject!("a", "c") # => {"b" => 2, "d" => 4}
    hash                   # => {"b" => 2, "d" => 4}

def select(& : K, V -> ) : Hash(K, V) #

Returns a new hash consisting of entries for which the block is truthy.

    h = {"a" => 100, "b" => 200, "c" => 300}
    h.select { |k, v| k > "a" } # => {"b" => 200, "c" => 300}
    h.select { |k, v| v < 200 } # => {"a" => 100}

def select(keys : Enumerable) : Hash(K, V) #

Returns a new `Hash` with the given keys.

    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select({"a", "c"})    # => {"a" => 1, "c" => 3}
    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select("a", "c")      # => {"a" => 1, "c" => 3}
    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select(["a", "c"])    # => {"a" => 1, "c" => 3}
    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select(Set{"a", "c"}) # => {"a" => 1, "c" => 3}

def select(*keys) : Hash(K, V) #

Returns a new `Hash` with the given keys.

    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select({"a", "c"})    # => {"a" => 1, "c" => 3}
    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select("a", "c")      # => {"a" => 1, "c" => 3}
    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select(["a", "c"])    # => {"a" => 1, "c" => 3}
    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select(Set{"a", "c"}) # => {"a" => 1, "c" => 3}

def select!(& : K, V -> ) : self #

Equivalent to `Hash#select` but makes modification on the current object rather than returning a new one. Returns `self`.

def select!(keys : Indexable) : self #

Removes every element except the given ones.

    h1 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!({"a", "c"})
    h2 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!("a", "c")
    h3 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!(["a", "c"])
    h4 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!(Set{"a", "c"})
    h1 == h2 == h3 == h4 # => true
    h1                   # => {"a" => 1, "c" => 3}

def select!(keys : Enumerable) : self #

Removes every element except the given ones.

    h1 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!({"a", "c"})
    h2 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!("a", "c")
    h3 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!(["a", "c"])
    h4 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!(Set{"a", "c"})
    h1 == h2 == h3 == h4 # => true
    h1                   # => {"a" => 1, "c" => 3}

def select!(*keys) : self #

Removes every element except the given ones.

    h1 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!({"a", "c"})
    h2 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!("a", "c")
    h3 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!(["a", "c"])
    h4 = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.select!(Set{"a", "c"})
    h1 == h2 == h3 == h4 # => true
    h1                   # => {"a" => 1, "c" => 3}

def shift : Tuple(K, V) #

Deletes and returns the first key-value pair in the hash, or raises `IndexError` if the hash is empty.

    hash = {"foo" => "bar", "baz" => "qux"}
    hash.shift # => {"foo", "bar"}
    hash       # => {"baz" => "qux"}

    hash = {} of String => String
    hash.shift # raises IndexError

def shift(&) #

Deletes and returns the first key-value pair in the hash. Yields to the given block if the hash is empty.

    hash = {"foo" => "bar", "baz" => "qux"}
    hash.shift { true } # => {"foo", "bar"}
    hash                # => {"baz" => "qux"}

    hash = {} of String => String
    hash.shift { true } # => true
    hash                # => {}

def shift? : Tuple(K, V) | Nil #

Same as `#shift`, but returns `nil` if the hash is empty.

    hash = {"foo" => "bar", "baz" => "qux"}
    hash.shift? # => {"foo", "bar"}
    hash        # => {"baz" => "qux"}

    hash = {} of String => String
    hash.shift? # => nil

def size : Int32 #

Returns the number of elements in this Hash.

def subset_of?(other : Hash) : Bool #

Returns `true` if `self` is a subset of other or equals to other.

def superset_of?(other : Hash) : Bool #

Returns `true` if other is a subset of `self`.

def to_a : Array(Tuple(K, V)) #

Returns an `Array` of `Tuple(K, V)` with key and values belonging to this Hash.

    h = {1 => 'a', 2 => 'b', 3 => 'c'}
    h.to_a # => [{1, 'a'}, {2, 'b'}, {3, 'c'}]

The order of the array follows the order the keys were inserted in the Hash.

def to_a(&block : Tuple(K, V) -> U) : Array(U) forall U #

Returns an `Array` with the results of running block against tuples with key and values belonging to this Hash.

    h = {"first_name" => "foo", "last_name" => "bar"}
    h.to_a { |_k, v| v.capitalize } # => ["Foo", "Bar"]

The order of the array follows the order the keys were inserted in the Hash.

def to_h : self #

Returns `self`.

def to_json(json : JSON::Builder) : Nil #

Serializes this Hash into JSON.

Keys are serialized by invoking `to_json_object_key` on them. Values are serialized with the usual `#to_json(json : JSON::Builder)` method.

def to_s(io : IO) : Nil #

Converts to a `String`.

    h = {"foo" => "bar"}
    h.to_s       # => "{\"foo\" => \"bar\"}"
    h.to_s.class # => String

def to_yaml(yaml : YAML::Nodes::Builder) : Nil #
def transform_keys(& : K, V -> K2) : Hash(K2, V) forall K2 #

Returns a new hash with all keys converted using the block operation. The block can change a type of keys. The block yields the key and value.

    hash = {:a => 1, :b => 2, :c => 3}
    hash.transform_keys { |key| key.to_s }                # => {"a" => 1, "b" => 2, "c" => 3}
    hash.transform_keys { |key, value| key.to_s * value } # => {"a" => 1, "bb" => 2, "ccc" => 3}

def transform_keys!(& : K, V -> K) : self #

Destructively transforms all keys using a block. Same as transform_keys but modifies in place. The block cannot change a type of keys. The block yields the key and value.

    hash = {"a" => 1, "b" => 2, "c" => 3}
    hash.transform_keys! { |key| key.upcase }
    hash # => {"A" => 1, "B" => 2, "C" => 3}
    hash.transform_keys! { |key, value| key * value }
    hash # => {"a" => 1, "bb" => 2, "ccc" => 3}

def transform_values(& : V, K -> V2) : Hash(K, V2) forall V2 #

Returns a new hash with the results of running block once for every value. The block can change a type of values. The block yields the value and key.

    hash = {:a => 1, :b => 2, :c => 3}
    hash.transform_values { |value| value + 1 }             # => {:a => 2, :b => 3, :c => 4}
    hash.transform_values { |value, key| "#{key}#{value}" } # => {:a => "a1", :b => "b2", :c => "c3"}

def transform_values!(& : V, K -> V) : self #

Destructively transforms all values using a block. Same as transform_values but modifies in place. The block cannot change a type of values. The block yields the value and key.

    hash = {:a => 1, :b => 2, :c => 3}
    hash.transform_values! { |value| value + 1 }
    hash # => {:a => 2, :b => 3, :c => 4}
    hash.transform_values! { |value, key| value + key.to_s[0].ord }
    hash # => {:a => 99, :b => 101, :c => 103}

See `#update` for updating a single value.

def update(key : K, & : V -> V) : V #

Updates the current value of key with the value returned by the given block (the current value is used as input for the block).

If no entry for key is present, but there's a default value (or default block) then that default value is used as input for the given block.

If no entry for key is present and the hash has no default value, it raises `KeyError`.

It returns the value used as input for the given block (ie. the old value if key present, or the default value)

    h = {"a" => 0, "b" => 1}
    h.update("b") { |v| v + 41 } # => 1
    h["b"]                       # => 42

    h = Hash(String, Int32).new(40)
    h.update("foo") { |v| v + 2 } # => 40
    h["foo"]                      # => 42

    h = {} of String => Int32
    h.update("a") { 42 } # raises KeyError

See `#transform_values!` for updating all the values.

def values : Array(V) #

Returns only the values as an `Array`.

    h = {"foo" => "bar", "baz" => "qux"}
    h.values # => ["bar", "qux"]

def values_at(*keys : K) #

Returns a tuple populated with the values of the given keys, with the same order. Raises if a key is not found.

    {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.values_at("a", "c") # => {1, 3}