summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-hash-ext/mrblib/hash.rb
blob: ce8fa357729e5131c0f1dec71ddabe8e73af1744 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
class Hash

  ##
  # 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}
  #

  def merge!(other, &block)
    raise "can't convert argument into Hash" unless other.respond_to?(:to_hash)
    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
    self
  end

  alias each_pair each
  alias update merge!

  ##
  #  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 <code>KeyError</code> exception; if <i>default</i> 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")
  #
  #  <em>produces:</em>
  #
  #     prog.rb:2:in `fetch': key not found (KeyError)
  #      from prog.rb:2
  #

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

  ##
  #  call-seq:
  #     hsh.delete_if {| key, value | block }  -> hsh
  #     hsh.delete_if                          -> an_enumerator
  #
  #  Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
  #  evaluates to <code>true</code>.
  #
  #  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}
  #

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

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