class Hash(K, V)
inherits Reference
¶
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
Iterable
Direct known subclasses
Crystal::HashStringType
Class methods¶
.zip(ary1 : Array(K), ary2 : Array(V))
¶
(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"}
.new(default_value : V, initial_capacity = nil)
¶
(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
Note
The default value is passed by reference:
arr = [1, 2, 3]
hash = Hash(String, Array(Int32)).new(arr)
hash["3"][1] = 4
arr # => [1, 4, 3]
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.
.new(pull : JSON::PullParser)
¶
(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.
.new(block : Hash(K, V), K -> V? = nil, *, initial_capacity = nil)
¶
(block : Hash(K, V), K -> V? = 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.
.new(initial_capacity = nil, &block : Hash(K, V), K -> V)
¶
(initial_capacity = nil, &block : Hash(K, V), K -> V)
Creates a new empty Hash
with a block that handles missing keys.
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.
Methods¶
#==(other : Hash)
¶
(other : Hash)
Compares with other. Returns true
if all key-value pairs are the same.
#[](key)
¶
(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
#[]=(key : K, value : V)
¶
(key : K, value : V)
Sets the value of key to the given value.
h = {} of String => String
h["foo"] = "bar"
h["foo"] # => "bar"
#[]?(key)
¶
(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
#clone
¶
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"}}
#compact
¶
Returns new Hash
without nil
values.
hash = {"hello" => "world", "foo" => nil}
hash.compact # => {"hello" => "world"}
#compact!
¶
Removes all nil
value from self
. Returns self
.
hash = {"hello" => "world", "foo" => nil}
hash.compact! # => {"hello" => "world"}
#compare_by_identity
¶
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
#compare_by_identity?
¶
Returns true
of this Hash is comparing keys by object_id
.
See compare_by_identity
.
#delete(key)
¶
(key)
Deletes the key-value pair and returns the value, otherwise returns nil
.
h = {"foo" => "bar"}
h.delete("foo") # => "bar"
h.fetch("foo", nil) # => nil
#delete
¶
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"
#dig(key : K, *subkeys)
¶
(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", "b", "c", "d", "e" # raises KeyError
#dig?(key : K, *subkeys)
¶
(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", "b", "c", "d", "e" # => nil
#dup
¶
Duplicates a Hash
.
hash_a = {"foo" => "bar"}
hash_b = hash_a.dup
hash_b.merge!({"baz" => "qux"})
hash_a # => {"foo" => "bar"}
#each(&) : Nil
¶
(&) : 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.
#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.
#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.
#each_key
¶
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.
#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.
#each_value
¶
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.
#empty?
¶
Returns true
when hash contains no key-value pairs.
h = Hash(String, String).new
h.empty? # => true
h = {"foo" => "bar"}
h.empty? # => false
#fetch
¶
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"
#fetch(key, default)
¶
(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"
#first_key?
¶
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
#first_value?
¶
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
#has_key?(key)
¶
(key)
Returns true
when key given by key exists, otherwise false
.
h = {"foo" => "bar"}
h.has_key?("foo") # => true
h.has_key?("bar") # => false
#has_value?(val)
¶
(val)
Returns true
when value given by value exists, otherwise false
.
h = {"foo" => "bar"}
h.has_value?("foo") # => false
h.has_value?("bar") # => true
#inspect(io : IO) : Nil
¶
(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.
class Person
def initialize(@name : String, @age : Int32)
end
end
Person.new("John", 32).inspect # => #<Person:0x10fd31f20 @name="John", @age=32>
#invert
¶
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"}
#key_for
¶
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"
#key_for(value)
¶
(value)
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)
#key_for?(value)
¶
(value)
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
#keys : Array(K)
¶
: Array(K)
Returns a new Array
with all the keys.
h = {"foo" => "bar", "baz" => "bar"}
h.keys # => ["foo", "baz"]
#last_key?
¶
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
#last_value?
¶
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
#merge(other : Hash(L, W)) forall L, W
¶
(other : Hash(L, 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"}
#merge!(other : Hash, &) : self
¶
(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}
#merge!(other : Hash)
¶
(other : Hash)
Similar to #merge
, but the receiver is modified.
hash = {"foo" => "bar"}
hash.merge!({"baz" => "qux"})
hash # => {"foo" => "bar", "baz" => "qux"}
#proper_superset_of?(other : Hash)
¶
(other : Hash)
Returns true
if other is a subset of self
or equals to self
.
#put
¶
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"
#rehash : Nil
¶
: Nil
Rebuilds the hash table based on the current value of each key.
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 method re-indexes the hash using the current key values.
#reject(&block : K, V -> _)
¶
(&block : K, V -> _)
Returns a new hash consisting of entries for which the block returns false
.
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}
#reject(*keys)
¶
(*keys)
Returns a new Hash
without the given keys.
{"a" => 1, "b" => 2, "c" => 3, "d" => 4}.reject("a", "c") # => {"b" => 2, "d" => 4}
#reject!(keys : Array | Tuple)
¶
(keys : Array | Tuple)
Removes a list of keys out of hash.
h = {"a" => 1, "b" => 2, "c" => 3, "d" => 4}.reject!("a", "c")
h # => {"b" => 2, "d" => 4}
#reject!(&block : K, V -> _)
¶
(&block : K, V -> _)
Equivalent to Hash#reject
, but makes modification on the current object rather than returning a new one. Returns self
.
#select(*keys)
¶
(*keys)
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}
#select(&block : K, V -> _)
¶
(&block : K, V -> _)
Returns a new hash consisting of entries for which the block returns true
.
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}
#select(keys : Array | Tuple)
¶
(keys : Array | Tuple)
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}
#select!(*keys)
¶
(*keys)
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"])
h1 == h2 == h3 # => true
h1 # => {"a" => 1, "c" => 3}
#select!(keys : Array | Tuple)
¶
(keys : Array | Tuple)
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"])
h1 == h2 == h3 # => true
h1 # => {"a" => 1, "c" => 3}
#select!(&block : K, V -> _)
¶
(&block : K, V -> _)
Equivalent to Hash#select
but makes modification on the current object rather than returning a new one. Returns self
.
#shift
¶
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
#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 # => {}
#shift?
¶
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
#subset_of?(other : Hash)
¶
(other : Hash)
Returns true
if self
is a subset of other or equals to other.
#to_a : Array(Tuple(K, V))
¶
: Array(Tuple(K, V))
Returns an array of tuples with key and values belonging to this Hash.
h = {1 => 'a', 2 => 'b', 3 => 'c'}
h.to_a # => [{1, 'a'}, {2, 'b'}, {3, 'c'}]
#to_json(json : JSON::Builder)
¶
(json : JSON::Builder)
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.
#to_s(io : IO) : Nil
¶
(io : IO) : Nil
Converts to a String
.
h = {"foo" => "bar"}
h.to_s # => "{\"foo\" => \"bar\"}"
h.to_s.class # => String
#transform_keys(&block : K -> K2) forall K2
¶
(&block : K -> K2) forall K2
Returns a new hash with all keys converted using the block operation. The block can change a type of keys.
hash = {:a => 1, :b => 2, :c => 3}
hash.transform_keys { |key| key.to_s } # => {"a" => 1, "b" => 2, "c" => 3}
#transform_values(&block : V -> V2) forall V2
¶
(&block : V -> 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.
hash = {:a => 1, :b => 2, :c => 3}
hash.transform_values { |value| value + 1 } # => {:a => 2, :b => 3, :c => 4}
#transform_values!(&block : V -> V)
¶
(&block : V -> V)
Destructively transforms all values using a block. Same as transform_values but modifies in place. The block cannot change a type of values.
hash = {:a => 1, :b => 2, :c => 3}
hash.transform_values! { |value| value + 1 }
hash # => {:a => 2, :b => 3, :c => 4}
#values : Array(V)
¶
: Array(V)
Returns only the values as an Array
.
h = {"foo" => "bar", "baz" => "qux"}
h.values # => ["bar", "qux"]
#values_at(*keys : K)
¶
(*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}