1## 2# Hash 3# 4# ISO 15.2.13 5class Hash 6 ## 7 # Equality---Two hashes are equal if they each contain the same number 8 # of keys and if each key-value pair is equal to (according to 9 # <code>Object#==</code>) the corresponding elements in the other 10 # hash. 11 # 12 # ISO 15.2.13.4.1 13 def ==(hash) 14 return true if self.equal?(hash) 15 unless Hash === hash 16 return false 17 end 18 return false if self.size != hash.size 19 self.each do |k,v| 20 return false unless hash.key?(k) 21 return false unless self[k] == hash[k] 22 end 23 return true 24 end 25 26 ## 27 # Returns <code>true</code> if <i>hash</i> and <i>other</i> are 28 # both hashes with the same content compared by eql?. 29 # 30 # ISO 15.2.13.4.32 (x) 31 def eql?(hash) 32 return true if self.equal?(hash) 33 unless Hash === hash 34 return false 35 end 36 return false if self.size != hash.size 37 self.each do |k,v| 38 return false unless hash.key?(k) 39 return false unless self[k].eql?(hash[k]) 40 end 41 return true 42 end 43 44 ## 45 # Delete the element with the key +key+. 46 # Return the value of the element if +key+ 47 # was found. Return nil if nothing was 48 # found. If a block is given, call the 49 # block with the value of the element. 50 # 51 # ISO 15.2.13.4.8 52 def delete(key, &block) 53 if block && !self.has_key?(key) 54 return block.call(key) 55 end 56 self.__delete(key) 57 end 58 59 ## 60 # Calls the given block for each element of +self+ 61 # and pass the key and value of each element. 62 # 63 # call-seq: 64 # hsh.each {| key, value | block } -> hsh 65 # hsh.each_pair {| key, value | block } -> hsh 66 # hsh.each -> an_enumerator 67 # hsh.each_pair -> an_enumerator 68 # 69 # 70 # If no block is given, an enumerator is returned instead. 71 # 72 # h = { "a" => 100, "b" => 200 } 73 # h.each {|key, value| puts "#{key} is #{value}" } 74 # 75 # <em>produces:</em> 76 # 77 # a is 100 78 # b is 200 79 # 80 # ISO 15.2.13.4.9 81 def each(&block) 82 return to_enum :each unless block 83 84 keys = self.keys 85 vals = self.values 86 len = self.size 87 i = 0 88 while i < len 89 block.call [keys[i], vals[i]] 90 i += 1 91 end 92 self 93 end 94 95 ## 96 # Calls the given block for each element of +self+ 97 # and pass the key of each element. 98 # 99 # call-seq: 100 # hsh.each_key {| key | block } -> hsh 101 # hsh.each_key -> an_enumerator 102 # 103 # If no block is given, an enumerator is returned instead. 104 # 105 # h = { "a" => 100, "b" => 200 } 106 # h.each_key {|key| puts key } 107 # 108 # <em>produces:</em> 109 # 110 # a 111 # b 112 # 113 # ISO 15.2.13.4.10 114 def each_key(&block) 115 return to_enum :each_key unless block 116 117 self.keys.each{|k| block.call(k)} 118 self 119 end 120 121 ## 122 # Calls the given block for each element of +self+ 123 # and pass the value of each element. 124 # 125 # call-seq: 126 # hsh.each_value {| value | block } -> hsh 127 # hsh.each_value -> an_enumerator 128 # 129 # If no block is given, an enumerator is returned instead. 130 # 131 # h = { "a" => 100, "b" => 200 } 132 # h.each_value {|value| puts value } 133 # 134 # <em>produces:</em> 135 # 136 # 100 137 # 200 138 # 139 # ISO 15.2.13.4.11 140 def each_value(&block) 141 return to_enum :each_value unless block 142 143 self.values.each{|v| block.call(v)} 144 self 145 end 146 147 ## 148 # Replaces the contents of <i>hsh</i> with the contents of other hash 149 # 150 # ISO 15.2.13.4.23 151 def replace(hash) 152 raise TypeError, "Hash required (#{hash.class} given)" unless Hash === hash 153 self.clear 154 hash.each_key{|k| 155 self[k] = hash[k] 156 } 157 if hash.default_proc 158 self.default_proc = hash.default_proc 159 else 160 self.default = hash.default 161 end 162 self 163 end 164 # ISO 15.2.13.4.17 165 alias initialize_copy replace 166 167 ## 168 # Return a hash which contains the content of 169 # +self+ and +other+. If a block is given 170 # it will be called for each element with 171 # a duplicate key. The value of the block 172 # will be the final value of this element. 173 # 174 # ISO 15.2.13.4.22 175 def merge(other, &block) 176 raise TypeError, "Hash required (#{other.class} given)" unless Hash === other 177 h = self.dup 178 if block 179 other.each_key{|k| 180 h[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k] 181 } 182 else 183 other.each_key{|k| h[k] = other[k]} 184 end 185 h 186 end 187 188 # internal method for Hash inspection 189 def _inspect(recur_list) 190 return "{}" if self.size == 0 191 return "{...}" if recur_list[self.object_id] 192 recur_list[self.object_id] = true 193 ary=[] 194 keys=self.keys 195 vals=self.values 196 size=keys.size 197 i=0 198 while i<size 199 ary<<(keys[i]._inspect(recur_list) + "=>" + vals[i]._inspect(recur_list)) 200 i+=1 201 end 202 "{"+ary.join(", ")+"}" 203 end 204 ## 205 # Return the contents of this hash as a string. 206 # 207 # ISO 15.2.13.4.30 (x) 208 def inspect 209 self._inspect({}) 210 end 211 # ISO 15.2.13.4.31 (x) 212 alias to_s inspect 213 214 ## 215 # call-seq: 216 # hsh.reject! {| key, value | block } -> hsh or nil 217 # hsh.reject! -> an_enumerator 218 # 219 # Equivalent to <code>Hash#delete_if</code>, but returns 220 # <code>nil</code> if no changes were made. 221 # 222 # 1.8/1.9 Hash#reject! returns Hash; ISO says nothing. 223 # 224 def reject!(&block) 225 return to_enum :reject! unless block 226 227 keys = [] 228 self.each{|k,v| 229 if block.call([k, v]) 230 keys.push(k) 231 end 232 } 233 return nil if keys.size == 0 234 keys.each{|k| 235 self.delete(k) 236 } 237 self 238 end 239 240 ## 241 # call-seq: 242 # hsh.reject {|key, value| block} -> a_hash 243 # hsh.reject -> an_enumerator 244 # 245 # Returns a new hash consisting of entries for which the block returns false. 246 # 247 # If no block is given, an enumerator is returned instead. 248 # 249 # h = { "a" => 100, "b" => 200, "c" => 300 } 250 # h.reject {|k,v| k < "b"} #=> {"b" => 200, "c" => 300} 251 # h.reject {|k,v| v > 100} #=> {"a" => 100} 252 # 253 # 1.8/1.9 Hash#reject returns Hash; ISO says nothing. 254 # 255 def reject(&block) 256 return to_enum :reject unless block 257 258 h = {} 259 self.each{|k,v| 260 unless block.call([k, v]) 261 h[k] = v 262 end 263 } 264 h 265 end 266 267 ## 268 # call-seq: 269 # hsh.select! {| key, value | block } -> hsh or nil 270 # hsh.select! -> an_enumerator 271 # 272 # Equivalent to <code>Hash#keep_if</code>, but returns 273 # <code>nil</code> if no changes were made. 274 # 275 # 1.9 Hash#select! returns Hash; ISO says nothing. 276 # 277 def select!(&block) 278 return to_enum :select! unless block 279 280 keys = [] 281 self.each{|k,v| 282 unless block.call([k, v]) 283 keys.push(k) 284 end 285 } 286 return nil if keys.size == 0 287 keys.each{|k| 288 self.delete(k) 289 } 290 self 291 end 292 293 ## 294 # call-seq: 295 # hsh.select {|key, value| block} -> a_hash 296 # hsh.select -> an_enumerator 297 # 298 # Returns a new hash consisting of entries for which the block returns true. 299 # 300 # If no block is given, an enumerator is returned instead. 301 # 302 # h = { "a" => 100, "b" => 200, "c" => 300 } 303 # h.select {|k,v| k > "a"} #=> {"b" => 200, "c" => 300} 304 # h.select {|k,v| v < 200} #=> {"a" => 100} 305 # 306 # 1.9 Hash#select returns Hash; ISO says nothing 307 # 308 def select(&block) 309 return to_enum :select unless block 310 311 h = {} 312 self.each{|k,v| 313 if block.call([k, v]) 314 h[k] = v 315 end 316 } 317 h 318 end 319end 320 321## 322# Hash is enumerable 323# 324# ISO 15.2.13.3 325class Hash 326 include Enumerable 327end 328