Class: Hash

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
mrblib/hash.rb,
mrbgems/mruby-hash-ext/mrblib/hash.rb

Overview

Hash

ISO 15.2.13

Constant Summary

Constants included from Enumerable

Enumerable::NONE

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#all?, #any?, #chain, #chunk, #chunk_while, #collect, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #filter_map, #find_all, #find_index, #first, #flat_map, #grep, #grep_v, #group_by, #hash, #include?, #inject, #lazy, #max, #max_by, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reverse_each, #sort, #sort_by, #sum, #take, #take_while, #tally, #uniq, #zip

Class Method Details

.[](*object) ⇒ Object

call-seq: Hash[ key, value, … ] -> new_hash Hash[ [ [key, value], … ] ] -> new_hash Hash[ object ] -> new_hash

Creates a new hash populated with the given objects.

Similar to the literal { key => value, ... }. In the first form, keys and values occur in pairs, so there must be an even number of arguments.

The second and third form take a single argument which is either an array of key-value pairs or an object convertible to a hash.

Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200}
Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 26

def self.[](*object)
  length = object.length
  if length == 1
    o = object[0]
    if Hash === o
      h = self.new
      o.each { |k, v| h[k] = v }
      return h
    elsif o.respond_to?(:to_a)
      h = self.new
      o.to_a.each do |i|
        raise ArgumentError, "wrong element type #{i.class} (expected array)" unless i.respond_to?(:to_a)
        k, v = nil
        case i.size
        when 2
          k = i[0]
          v = i[1]
        when 1
          k = i[0]
        else
          raise ArgumentError, "invalid number of elements (#{i.size} for 1..2)"
        end
        h[k] = v
      end
      return h
    end
  end
  unless length % 2 == 0
    raise ArgumentError, 'odd number of arguments for Hash'
  end
  h = self.new
  0.step(length - 2, 2) do |i|
    h[object[i]] = object[i + 1]
  end
  h
end

Instance Method Details

#<(hash) ⇒ Object

call-seq: hash < other -> true or false

Returns true if hash is subset of other.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 < h2    #=> true
h2 < h1    #=> false
h1 < h1    #=> false

Raises:



303
304
305
306
307
308
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 303

def <(hash)
  raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
  size < hash.size and all? {|key, val|
    hash.key?(key) and hash[key] == val
  }
end

#<=(hash) ⇒ Object

call-seq: hash <= other -> true or false

Returns true if hash is subset of other or equals to other.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 <= h2   #=> true
h2 <= h1   #=> false
h1 <= h1   #=> true

Raises:



323
324
325
326
327
328
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 323

def <=(hash)
  raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
  size <= hash.size and all? {|key, val|
    hash.key?(key) and hash[key] == val
  }
end

#==(hash) ⇒ Object

call-seq: hash == object -> true or false

Equality—Two hashes are equal if they each contain the same number of keys and if each key-value pair is equal to (according to Object#==) the corresponding elements in the other hash.

ISO 15.2.13.4.1



22
23
24
25
26
27
28
29
30
31
32
33
# File 'mrblib/hash.rb', line 22

def ==(hash)
  return true if self.equal?(hash)
  unless Hash === hash
    return false
  end
  return false if self.size != hash.size
  self.each do |k,v|
    return false unless hash.key?(k)
    return false unless self[k] == hash[k]
  end
  return true
end

#>(hash) ⇒ Object

call-seq: hash > other -> true or false

Returns true if other is subset of hash.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 > h2    #=> false
h2 > h1    #=> true
h1 > h1    #=> false

Raises:



343
344
345
346
347
348
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 343

def >(hash)
  raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
  size > hash.size and hash.all? {|key, val|
    key?(key) and self[key] == val
  }
end

#>=(hash) ⇒ Object

call-seq: hash >= other -> true or false

Returns true if other is subset of hash or equals to hash.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 >= h2   #=> false
h2 >= h1   #=> true
h1 >= h1   #=> true

Raises:



363
364
365
366
367
368
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 363

def >=(hash)
  raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
  size >= hash.size and hash.all? {|key, val|
    key?(key) and self[key] == val
  }
end

#compactObject

call-seq: hsh.compact -> new_hsh

Returns a new hash with the nil values/key pairs removed

h = { a: 1, b: false, c: nil } h.compact #=> { a: 1, b: false } h #=> { a: 1, b: false, c: nil }



129
130
131
132
133
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 129

def compact
  h=self.dup
  h.__compact
  h
end

#compact!Object

call-seq: hsh.compact! -> hsh

Removes all nil values from the hash. Returns the hash. Returns nil if the hash does not contain nil values.

h = { a: 1, b: false, c: nil } h.compact! #=> { a: 1, b: false }



115
116
117
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 115

def compact!
  self.__compact
end

#delete(key, &block) ⇒ Object

call-seq: hash.delete(key) -> value or nil hash.delete(key) {|key| … } -> object

Delete the element with the key key. Return the value of the element if key was found. Return nil if nothing was found. If a block is given, call the block with the value of the element.

ISO 15.2.13.4.8



67
68
69
70
71
72
# File 'mrblib/hash.rb', line 67

def delete(key, &block)
  if block && !self.has_key?(key)
    return block.call(key)
  end
  self.__delete(key)
end

#delete_if(&block) ⇒ Object

call-seq: hsh.delete_if {| key, value | block } -> hsh hsh.delete_if -> an_enumerator

Deletes every key-value pair from hsh for which block evaluates to true.

If no block is given, an enumerator is returned instead.

h = { "a" => 100, "b" => 200, "c" => 300 }
h.delete_if {|key, value| key >= "b" }   #=> {"a"=>100}


191
192
193
194
195
196
197
198
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 191

def delete_if(&block)
  return to_enum :delete_if unless block

  self.each do |k, v|
    self.delete(k) if block.call(k, v)
  end
  self
end

#dig(idx, *args) ⇒ Object

call-seq: hsh.dig(key,…) -> object

Extracts the nested value specified by the sequence of key objects by calling dig at each step, returning nil if any intermediate step is nil.



378
379
380
381
382
383
384
385
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 378

def dig(idx,*args)
  n = self[idx]
  if args.size > 0
    n&.dig(*args)
  else
    n
  end
end

#each(&block) ⇒ Object Also known as: each_pair

call-seq: hsh.each {| key, value | block } -> hsh hsh.each_pair {| key, value | block } -> hsh hsh.each -> an_enumerator hsh.each_pair -> an_enumerator

Calls the given block for each element of self and pass the key and value of each element.

If no block is given, an enumerator is returned instead.

h = { "a" => 100, "b" => 200 }
h.each {|key, value| puts "#{key} is #{value}" }

produces:

a is 100 b is 200

ISO 15.2.13.4.9



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'mrblib/hash.rb', line 95

def each(&block)
  return to_enum :each unless block

  keys = self.keys
  vals = self.values
  len = self.size
  i = 0
  while i < len
    block.call [keys[i], vals[i]]
    i += 1
  end
  self
end

#each_key(&block) ⇒ Object

call-seq: hsh.each_key {| key | block } -> hsh hsh.each_key -> an_enumerator

Calls the given block for each element of self and pass the key of each element.

If no block is given, an enumerator is returned instead.

h = { “a” => 100, “b” => 200 } h.each_key {|key| puts key }

produces:

a b

ISO 15.2.13.4.10



128
129
130
131
132
133
# File 'mrblib/hash.rb', line 128

def each_key(&block)
  return to_enum :each_key unless block

  self.keys.each{|k| block.call(k)}
  self
end

#each_value(&block) ⇒ Object

call-seq: hsh.each_value {| value | block } -> self hsh.each_value -> an_enumerator

Calls the given block with each value; returns self:

If no block is given, an enumerator is returned instead.

h = { “a” => 100, “b” => 200 } h.each_value {|value| puts value }

produces:

100 200

ISO 15.2.13.4.11



153
154
155
156
157
158
# File 'mrblib/hash.rb', line 153

def each_value(&block)
  return to_enum :each_value unless block

  self.values.each{|v| block.call(v)}
  self
end

#eql?(hash) ⇒ Boolean

call-seq: hash.eql? object -> true or false

Returns true if hash and other are both hashes with the same content compared by eql?.

Returns:

  • (Boolean)


42
43
44
45
46
47
48
49
50
51
52
53
# File 'mrblib/hash.rb', line 42

def eql?(hash)
  return true if self.equal?(hash)
  unless Hash === hash
    return false
  end
  return false if self.size != hash.size
  self.each do |k,v|
    return false unless hash.key?(k)
    return false unless self[k].eql?(hash[k])
  end
  return true
end

#fetch(key, none = NONE, &block) ⇒ Object

call-seq: hsh.fetch(key [, default] ) -> obj hsh.fetch(key) {| key | block } -> obj

Returns a value from the hash for the given key. If the key can’t be found, there are several options: With no other arguments, it will raise an KeyError exception; if default is given, then that will be returned; if the optional code block is specified, then that will be run and its result returned.

h = { "a" => 100, "b" => 200 }
h.fetch("a")                            #=> 100
h.fetch("z", "go fish")                 #=> "go fish"
h.fetch("z") { |el| "go fish, #{el}"}   #=> "go fish, z"

The following example shows that an exception is raised if the key is not found and a default value is not supplied.

h = { "a" => 100, "b" => 200 }
h.fetch("z")

produces:

prog.rb:2:in 'fetch': key not found (KeyError)
 from prog.rb:2


163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 163

def fetch(key, none=NONE, &block)
  unless self.key?(key)
    if block
      block.call(key)
    elsif !NONE.equal?(none)
      none
    else
      raise KeyError, "Key not found: #{key.inspect}"
    end
  else
    self[key]
  end
end

#fetch_values(*keys, &block) ⇒ Object

call-seq: hsh.fetch_values(key, …) -> array hsh.fetch_values(key, …) { |key| block } -> array

Returns an array containing the values associated with the given keys but also raises KeyError when one of keys can’t be found. Also see Hash#values_at and Hash#fetch.

h = { “cat” => “feline”, “dog” => “canine”, “cow” => “bovine” }

h.fetch_values(“cow”, “cat”) #=> [“bovine”, “feline”] h.fetch_values(“cow”, “bird”) # raises KeyError h.fetch_values(“cow”, “bird”) { |k| k.upcase } #=> [“bovine”, “BIRD”]



479
480
481
482
483
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 479

def fetch_values(*keys, &block)
  keys.map do |k|
    self.fetch(k, &block)
  end
end

#flatten(level = 1) ⇒ Object

call-seq: hash.flatten -> an_array hash.flatten(level) -> an_array

Returns a new array that is a one-dimensional flattening of this hash. That is, for every key or value that is an array, extract its elements into the new array. Unlike Array#flatten, this method does not flatten recursively by default. The optional level argument determines the level of recursion to flatten.

a =  {1=> "one", 2 => [2,"two"], 3 => "three"}
a.flatten    # => [1, "one", 2, [2, "two"], 3, "three"]
a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]


216
217
218
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 216

def flatten(level=1)
  self.to_a.flatten(level)
end

#invertObject

call-seq: hsh.invert -> new_hash

Returns a new hash created by using hsh’s values as keys, and the keys as values.

h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
h.invert   #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}


231
232
233
234
235
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 231

def invert
  h = self.class.new
  self.each {|k, v| h[v] = k }
  h
end

#keep_if(&block) ⇒ Object

call-seq: hsh.keep_if {| key, value | block } -> hsh hsh.keep_if -> an_enumerator

Deletes every key-value pair from hsh for which block evaluates to false.

If no block is given, an enumerator is returned instead.



248
249
250
251
252
253
254
255
256
257
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 248

def keep_if(&block)
  return to_enum :keep_if unless block

  self.each do |k, v|
    unless block.call([k, v])
      self.delete(k)
    end
  end
  self
end

#key(val) ⇒ Object

call-seq: hsh.key(value) -> key

Returns the key of an occurrence of a given value. If the value is not found, returns nil.

h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
h.key(200)   #=> "b"
h.key(300)   #=> "c"
h.key(999)   #=> nil


272
273
274
275
276
277
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 272

def key(val)
  self.each do |k, v|
    return k if v == val
  end
  nil
end

#merge(*others, &block) ⇒ Object

call-seq: hsh.merge(other_hash..) -> hsh hsh.merge(other_hash..){|key, oldval, newval| block} -> hsh

Returns the new Hash formed by merging each of other_hashes into a copy of self.

Each argument in other_hashes must be a Hash. Adds the contents of other_hash to hsh. If no block is specified, entries with duplicate keys are overwritten with the values from other_hash, otherwise the value of each duplicate key is determined by calling the block with the key, its value in hsh and its value in other_hash.

Example: h = 0, bar: 1, baz: 2 h1 = 3, bar: 4 h2 = 5, bat:6 h3 = h.merge(h1, h2) { |key, old_value, new_value| old_value + new_value } h3 # => :bar=>5, :baz=>2, :bat=>9, :bam=>5

ISO 15.2.13.4.22



183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'mrblib/hash.rb', line 183

def merge(*others, &block)
  h = self.dup
  return h.__merge(*others) unless block
  i=0; len=others.size
  while i<len
    other = others[i]
    i += 1
    raise TypeError, "Hash required (#{other.class} given)" unless Hash === other
    other.each_key{|k|
      h[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k]
    }
  end
  h
end

#merge!(*others, &block) ⇒ Object Also known as: update

call-seq: hsh.merge!(other_hash..) -> hsh hsh.merge!(other_hash..){|key, oldval, newval| block} -> hsh

Adds the contents of other_hash to hsh. If no block is specified, entries with duplicate keys are overwritten with the values from other_hash, otherwise the value of each duplicate key is determined by calling the block with the key, its value in hsh and its value in other_hash.

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2)   #=> {"a"=>100, "b"=>254, "c"=>300}

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2) { |key, v1, v2| v1 }
                #=> {"a"=>100, "b"=>200, "c"=>300}


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 84

def merge!(*others, &block)
  i = 0; len=others.size
  return self.__merge(*others) unless block
  while i<len
    other = others[i]
    i += 1
    raise TypeError, "Hash required (#{other.class} given)" unless Hash === other
    if block
      other.each_key{|k|
        self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k]
      }
    else
      other.each_key{|k| self[k] = other[k]}
    end
  end
  self
end

#reject(&block) ⇒ Object

call-seq: hsh.reject {|key, value| block} -> a_hash hsh.reject -> an_enumerator

Returns a new hash consisting of entries for which the block returns false.

If no block is given, an enumerator is returned instead.

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

1.8/1.9 Hash#reject returns Hash; ISO says nothing.



239
240
241
242
243
244
245
246
247
248
249
# File 'mrblib/hash.rb', line 239

def reject(&block)
  return to_enum :reject unless block

  h = {}
  self.each{|k,v|
    unless block.call([k, v])
      h[k] = v
    end
  }
  h
end

#reject!(&block) ⇒ Object

call-seq: hsh.reject! {| key, value | block } -> hsh or nil hsh.reject! -> an_enumerator

Equivalent to Hash#delete_if, but returns nil if no changes were made.

1.8/1.9 Hash#reject! returns Hash; ISO says nothing.



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'mrblib/hash.rb', line 208

def reject!(&block)
  return to_enum :reject! unless block

  keys = []
  self.each{|k,v|
    if block.call([k, v])
      keys.push(k)
    end
  }
  return nil if keys.size == 0
  keys.each{|k|
    self.delete(k)
  }
  self
end

#select(&block) ⇒ Object Also known as: filter

call-seq: hsh.select {|key, value| block} -> a_hash hsh.select -> an_enumerator

Returns a new hash consisting of entries for which the block returns true.

If no block is given, an enumerator is returned instead.

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}

1.9 Hash#select returns Hash; ISO says nothing



292
293
294
295
296
297
298
299
300
301
302
# File 'mrblib/hash.rb', line 292

def select(&block)
  return to_enum :select unless block

  h = {}
  self.each{|k,v|
    if block.call([k, v])
      h[k] = v
    end
  }
  h
end

#select!(&block) ⇒ Object Also known as: filter!

call-seq: hsh.select! {| key, value | block } -> hsh or nil hsh.select! -> an_enumerator

Equivalent to Hash#keep_if, but returns nil if no changes were made.

1.9 Hash#select! returns Hash; ISO says nothing.



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'mrblib/hash.rb', line 261

def select!(&block)
  return to_enum :select! unless block

  keys = []
  self.each{|k,v|
    unless block.call([k, v])
      keys.push(k)
    end
  }
  return nil if keys.size == 0
  keys.each{|k|
    self.delete(k)
  }
  self
end

#to_hObject

call-seq: hsh.to_h -> hsh or new_hash

Returns self. If called on a subclass of Hash, converts the receiver to a Hash object.



286
287
288
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 286

def to_h
  self
end

#to_procObject



460
461
462
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 460

def to_proc
  ->x{self[x]}
end

#transform_keys(&block) ⇒ Object

call-seq: hsh.transform_keys {|key| block } -> new_hash hsh.transform_keys -> an_enumerator

Returns a new hash, with the keys computed from running the block once for each key in the hash, and the values unchanged.

If no block is given, an enumerator is returned instead.



397
398
399
400
401
402
403
404
405
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 397

def transform_keys(&block)
  return to_enum :transform_keys unless block
  hash = {}
  self.keys.each do |k|
    new_key = block.call(k)
    hash[new_key] = self[k]
  end
  hash
end

#transform_keys!(&block) ⇒ Object

call-seq: hsh.transform_keys! {|key| block } -> hsh hsh.transform_keys! -> an_enumerator

Invokes the given block once for each key in hsh, replacing it with the new key returned by the block, and then returns hsh.

If no block is given, an enumerator is returned instead.



416
417
418
419
420
421
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 416

def transform_keys!(&block)
  return to_enum :transform_keys! unless block
  hash = self.transform_keys(&block)
  self.replace(hash)
  self
end

#transform_values(&b) ⇒ Object

call-seq: hsh.transform_values {|value| block } -> new_hash hsh.transform_values -> an_enumerator

Returns a new hash with the results of running the block once for every value. This method does not change the keys.

If no block is given, an enumerator is returned instead.



433
434
435
436
437
438
439
440
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 433

def transform_values(&b)
  return to_enum :transform_values unless block_given?
  hash = {}
  self.keys.each do |k|
    hash[k] = yield(self[k])
  end
  hash
end

#transform_values!(&b) ⇒ Object

call-seq: hsh.transform_values! {|key| block } -> hsh hsh.transform_values! -> an_enumerator

Invokes the given block once for each value in the hash, replacing with the new value returned by the block, and then returns hsh.

If no block is given, an enumerator is returned instead.



452
453
454
455
456
457
458
# File 'mrbgems/mruby-hash-ext/mrblib/hash.rb', line 452

def transform_values!(&b)
  return to_enum :transform_values! unless block_given?
  self.keys.each do |k|
    self[k] = yield(self[k])
  end
  self
end