|
1 | 1 | # About |
2 | 2 |
|
3 | | -## Creating hashes |
| 3 | +[Hashes][hash] are also known as dictionary or map in other languages, they are a mutable unsorted collection which maps keys to values. |
| 4 | +Each key is unique and is used to retrieve the corresponding value. |
| 5 | +The keys can be of any data type which is hashable (has a `hash` method), this includes strings, numbers, and most data types and objects in Ruby. |
4 | 6 |
|
| 7 | +Even though Hashes are unordered collections, [Ruby maintains the insertion order of key-value pairs][entry_order]. |
| 8 | +This means that when you iterate over a `Hash`, the pairs will be returned in the order they were added. |
| 9 | +However, deleting elements may affect the order of remaining elements. |
| 10 | +Hashes behavior of maintaining insertion order was introduced in Ruby [1.9][ruby-1.9]. |
5 | 11 |
|
| 12 | +## Creating Hashes |
6 | 13 |
|
7 | | -## Indexing |
| 14 | +You can create a `Hash` using curly braces `{}` with key-value pairs formed as `key => value` and separated by commas: |
| 15 | + |
| 16 | +```ruby |
| 17 | +my_hash = {"name" => "Alice", "age" => 30, "city" => "New York"} |
| 18 | +``` |
| 19 | + |
| 20 | +You can also mix and match different types of keys and values: |
| 21 | + |
| 22 | +```ruby |
| 23 | +my_hash = {1 => "one", :two => 2, "three" => [3, "three"]} |
| 24 | +``` |
| 25 | + |
| 26 | +Alternatively if the keys are symbols, you can use a more the newer syntax which was introcued in Ruby 1.9: |
| 27 | + |
| 28 | +```ruby |
| 29 | +my_hash = {name: "Alice", age: 30, city: "New York"} |
| 30 | +``` |
| 31 | + |
| 32 | +You can create an empty `Hash` using the `Hash.new` method: |
| 33 | + |
| 34 | +```ruby |
| 35 | +empty_hash = Hash.new |
| 36 | +``` |
| 37 | + |
| 38 | +## Accessing values |
| 39 | + |
| 40 | +You can access values in a `Hash` instance using its corresponding keys, the syntax reminds of array indexing, but using the key instead of an index: |
| 41 | + |
| 42 | +```ruby |
| 43 | +my_hash = {"name" => "Alice", "age" => 30, "city" => "New York"} |
| 44 | +my_hash["name"] |
| 45 | +# => "Alice" |
| 46 | +``` |
| 47 | + |
| 48 | +If the key does not exist in the `Hash` instance, the `[]` method will return `nil`: |
| 49 | + |
| 50 | +```ruby |
| 51 | +my_hash = {"name" => "Alice", "age" => 30} |
| 52 | +my_hash["city"] |
| 53 | +# => nil |
| 54 | +``` |
| 55 | + |
| 56 | +If the disired behavior is to not return `nil` for non-existing keys, another way of accessing values is by using the [`fetch`][fetch] method, which allows you provide a default value for non-existing keys. |
| 57 | +If the `fetch` method is used without a default value and the key does not exist, it will raise a `KeyError` exception. |
| 58 | + |
| 59 | +```ruby |
| 60 | +my_hash = {"name" => "Alice", "age" => 30} |
| 61 | +my_hash.fetch("city", "Unknown") |
| 62 | +# => "Unknown" |
| 63 | + |
| 64 | +my_hash.fetch("city") |
| 65 | +# => KeyError: key not found: "city" |
| 66 | +``` |
8 | 67 |
|
9 | 68 | ## Modifying |
10 | 69 |
|
| 70 | +You can add or update key-value pairs in a `Hash` instance by assigning a value to a key using the assignment operator `=`. |
| 71 | +Assigning a value to an existing key will update the value, while assigning a value to a new key will add a new key-value pair: |
| 72 | + |
| 73 | +```ruby |
| 74 | +my_hash = {"name" => "Alice", "age" => 30} |
| 75 | +my_hash["city"] = "New York" |
| 76 | +my_hash["age"] = 31 |
| 77 | + |
| 78 | +my_hash |
| 79 | +# => {"name" => "Alice", "age" => 31, "city" => "New York"} |
| 80 | +``` |
| 81 | + |
| 82 | +## Default values |
| 83 | + |
| 84 | +When fetching a value with `[]` for a key that does not exist in the `Hash` instance, Ruby returns `nil` by default. |
| 85 | + |
| 86 | +```ruby |
| 87 | +my_hash = {"name" => "Alice"} |
| 88 | +my_hash["age"] |
| 89 | +# => nil |
| 90 | +``` |
| 91 | + |
| 92 | +This might not always be desirable, so you can set a default value for the `Hash` instance using `Hash.new(default_value)`. |
| 93 | +See that the default value is returned only for keys that do not exist in the `Hash` instance. |
| 94 | + |
| 95 | +```ruby |
| 96 | +my_hash = Hash.new("unknown") |
| 97 | +my_hash["name"] = "Alice" |
| 98 | +my_hash["age"] |
| 99 | +# => "unknown" |
| 100 | + |
| 101 | +my_hash["name"] |
| 102 | +# => "Alice" |
| 103 | +``` |
| 104 | + |
| 105 | +~~~~exercism/note |
| 106 | +Be cautious when using mutable objects (like Arrays or other Hashes) as default values, as they can lead to unexpected behavior. |
| 107 | +~~~~ |
| 108 | + |
| 109 | +## Deleting key-value pairs |
| 110 | + |
| 111 | +You can delete a key-value pair from a `Hash` instance using the [`delete`][delete] method, which takes the key as an argument: |
| 112 | + |
| 113 | +```ruby |
| 114 | +my_hash = {"name" => "Alice", "age" => 30, "city" => "New York"} |
| 115 | +my_hash.delete("age") |
| 116 | +my_hash |
| 117 | +# => {"name" => "Alice", "city" => "New York"} |
| 118 | +``` |
| 119 | + |
11 | 120 | ## Methods |
12 | 121 |
|
13 | | -has_value? |
14 | | -include? |
| 122 | +There are several useful instance methods available for Hashes in Ruby. |
| 123 | +Here are some commonly used ones: |
| 124 | + |
| 125 | +### `has_value?` and `include?` |
| 126 | + |
| 127 | +You can check if a `Hash` instance contains a specific value using the [`has_value?`][has_value?] method. |
| 128 | + |
| 129 | +```ruby |
| 130 | +my_hash = {"name" => "Alice", "age" => 30} |
| 131 | +my_hash.has_value?(30) |
| 132 | +# => true |
| 133 | +my_hash.has_value?(25) |
| 134 | +# => false |
| 135 | +``` |
| 136 | + |
| 137 | +You can check if a `Hash` instance contains a specific key using the [`include?`][include?] method. |
| 138 | + |
| 139 | +```ruby |
| 140 | +my_hash = {"name" => "Alice", "age" => 30} |
| 141 | +my_hash.include?("name") |
| 142 | +# => true |
| 143 | +my_hash.include?("city") |
| 144 | +# => false |
| 145 | +``` |
| 146 | + |
| 147 | +### `keys` and `values` |
| 148 | + |
| 149 | +You can retrieve all the keys of a `Hash` instance using the [`keys`][keys] method, which returns an array of keys. |
| 150 | + |
| 151 | +```ruby |
| 152 | +my_hash = {"name" => "Alice", "age" => 30} |
| 153 | +my_hash.keys |
| 154 | +# => ["name", "age"] |
| 155 | +``` |
| 156 | + |
| 157 | +You can retrieve all the values of a `Hash` instance using the [`values`][values] method, which returns an array of values. |
| 158 | + |
| 159 | +```ruby |
| 160 | +my_hash = {"name" => "Alice", "age" => 30} |
| 161 | +my_hash.values |
| 162 | +# => ["Alice", 30] |
| 163 | +``` |
| 164 | + |
| 165 | +## Iterating over Hashes |
| 166 | + |
| 167 | +You can iterate over the key-value pairs in a `Hash` instance using the `each_pair` method. |
| 168 | +This will give you access to both the key and the value for each pair: |
| 169 | + |
| 170 | +```ruby |
| 171 | +my_hash = {"name" => "Alice", "age" => 30} |
| 172 | +my_hash.each_pair do |key, value| |
| 173 | + puts "#{key}: #{value}" |
| 174 | +end |
| 175 | +# Output: |
| 176 | +# name: Alice |
| 177 | +# age: 30 |
| 178 | +``` |
| 179 | + |
| 180 | +You can also iterate over just the keys or just the values using the [`each_key`][each_key] or [`each_value`][each_value] methods, respectively: |
| 181 | + |
| 182 | +```ruby |
| 183 | +my_hash = {"name" => "Alice", "age" => 30} |
| 184 | +my_hash.each_key do |key| |
| 185 | + puts key |
| 186 | +end |
| 187 | +# Output: |
| 188 | +# name |
| 189 | +# age |
| 190 | +``` |
15 | 191 |
|
16 | | -keys |
17 | | -values |
| 192 | +[entry_order]: https://docs.ruby-lang.org/en/master/Hash.html#class-Hash-label-Entry+Order |
| 193 | +[each_pair]: https://docs.ruby-lang.org/en/master/Hash.html#method-i-each_pair |
| 194 | +[each_key]: https://docs.ruby-lang.org/en/master/Hash.html#method-i-each_key |
| 195 | +[keys]: https://docs.ruby-lang.org/en/master/Hash.html#method-i-keys |
| 196 | +[each_value]: https://docs.ruby-lang.org/en/master/Hash.html#method-i-each_value |
| 197 | +[values]: https://docs.ruby-lang.org/en/master/Hash.html#method-i-values |
| 198 | +[has_value?]: https://docs.ruby-lang.org/en/master/Hash.html#method-i-has_value-3F |
| 199 | +[include?]: https://docs.ruby-lang.org/en/master/Hash.html#method-i-include-3F |
| 200 | +[hash]: https://docs.ruby-lang.org/en/master/Hash.html |
| 201 | +[fetch]: https://docs.ruby-lang.org/en/master/Hash.html#method-i-fetch |
| 202 | +[delete]: https://docs.ruby-lang.org/en/master/Hash.html#method-i-delete |
| 203 | +[ruby-1.9]: https://ruby-doc.org/3.4/NEWS/NEWS-1_9_1.html |
0 commit comments