diff options
-rw-r--r-- | hash.c | 94 | ||||
-rw-r--r-- | test/ruby/test_hash.rb | 24 |
2 files changed, 86 insertions, 32 deletions
@@ -2548,16 +2548,23 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) /* * call-seq: - * hsh.merge!(other_hash) -> hsh - * hsh.update(other_hash) -> hsh - * hsh.merge!(other_hash){|key, oldval, newval| block} -> hsh - * hsh.update(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 + * hsh.merge!(other_hash1, other_hash2, ...) -> hsh + * hsh.update(other_hash1, other_hash2, ...) -> hsh + * hsh.merge!(other_hash1, other_hash2, ...){|key, oldval, newval| block} + * -> hsh + * hsh.update(other_hash1, other_hash2, ...){|key, oldval, newval| block} + * -> hsh + * + * Adds the contents of _other_hash_s to _hsh_ repeatedly. If no block is + * specified, entries with duplicate keys are overwritten with the values from + * each _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_. + * each _other_hash_. The method also can be called with no argument, + * then nothing will change in the receiver. + * + * h1 = { "a" => 100, "b" => 200 } + * h1.merge!() #=> {"a"=>100, "b"=>200} + * h1 #=> {"a"=>100, "b"=>200} * * h1 = { "a" => 100, "b" => 200 } * h2 = { "b" => 254, "c" => 300 } @@ -2566,23 +2573,36 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) * * h1 = { "a" => 100, "b" => 200 } * h2 = { "b" => 254, "c" => 300 } - * h1.merge!(h2) { |key, v1, v2| v1 } - * #=> {"a"=>100, "b"=>200, "c"=>300} - * h1 #=> {"a"=>100, "b"=>200, "c"=>300} + * h3 = { "b" => 100, "d" => 400 } + * h1.merge!(h2, h3) + * #=> {"a"=>100, "b"=>100, "c"=>300, "d"=>400} + * h1 #=> {"a"=>100, "b"=>100, "c"=>300, "d"=>400} + * + * h1 = { "a" => 100, "b" => 200 } + * h2 = { "b" => 254, "c" => 300 } + * h3 = { "b" => 100, "d" => 400 } + * h1.merge!(h2, h3) { |key, v1, v2| v1 } + * #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400} + * h1 #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400} */ static VALUE -rb_hash_update(VALUE hash1, VALUE hash2) +rb_hash_update(int argc, VALUE *argv, VALUE self) { - rb_hash_modify(hash1); - hash2 = to_hash(hash2); - if (rb_block_given_p()) { - rb_hash_foreach(hash2, rb_hash_update_block_i, hash1); - } - else { - rb_hash_foreach(hash2, rb_hash_update_i, hash1); + int i; + bool block_given = rb_block_given_p(); + + rb_hash_modify(self); + for (i = 0; i < argc; i++){ + VALUE hash = to_hash(argv[i]); + if (block_given) { + rb_hash_foreach(hash, rb_hash_update_block_i, self); + } + else { + rb_hash_foreach(hash, rb_hash_update_i, self); + } } - return hash1; + return self; } struct update_func_arg { @@ -2641,28 +2661,38 @@ rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func) /* * call-seq: - * hsh.merge(other_hash) -> new_hash - * hsh.merge(other_hash){|key, oldval, newval| block} -> new_hash + * hsh.merge(other_hash1, other_hash2, ...) -> new_hash + * hsh.merge(other_hash1, other_hash2, ...){|key, oldval, newval| block} + * -> new_hash * - * Returns a new hash containing the contents of <i>other_hash</i> and + * Returns a new hash containing the contents of <i>other_hash</i>s and * the contents of <i>hsh</i>. If no block is specified, the value for - * entries with duplicate keys will be that of <i>other_hash</i>. Otherwise - * the value for each duplicate key is determined by calling the block - * with the key, its value in <i>hsh</i> and its value in <i>other_hash</i>. + * entries with duplicate keys will be that of each <i>other_hash</i>. + * Otherwise the value for each duplicate key is determined by calling + * the block with the key, its value in <i>hsh</i> and its value + * in each <i>other_hash</i>. The method also can be called with no argument, + * then a new hash, whose content is same as that of the receiver, + * will be returned; * * h1 = { "a" => 100, "b" => 200 } * h2 = { "b" => 254, "c" => 300 } + * h3 = { "b" => 100, "d" => 400 } + * h1.merge() #=> {"a"=>100, "b"=>200} * h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300} + * h1.merge(h2, h3) + * #=> {"a"=>100, "b"=>100, "c"=>300, "d"=>400} * h1.merge(h2){|key, oldval, newval| newval - oldval} * #=> {"a"=>100, "b"=>54, "c"=>300} + * h1.merge(h2, h3){|key, oldval, newval| newval - oldval} + * #=> {"a"=>100, "b"=>46, "c"=>300, "d"=>400} * h1 #=> {"a"=>100, "b"=>200} * */ static VALUE -rb_hash_merge(VALUE hash1, VALUE hash2) +rb_hash_merge(int argc, VALUE *argv, VALUE self) { - return rb_hash_update(rb_hash_dup(hash1), hash2); + return rb_hash_update(argc, argv, rb_hash_dup(self)); } static int @@ -4761,10 +4791,10 @@ Init_Hash(void) rb_define_method(rb_cHash, "slice", rb_hash_slice, -1); rb_define_method(rb_cHash, "clear", rb_hash_clear, 0); rb_define_method(rb_cHash, "invert", rb_hash_invert, 0); - rb_define_method(rb_cHash, "update", rb_hash_update, 1); + rb_define_method(rb_cHash, "update", rb_hash_update, -1); rb_define_method(rb_cHash, "replace", rb_hash_replace, 1); - rb_define_method(rb_cHash, "merge!", rb_hash_update, 1); - rb_define_method(rb_cHash, "merge", rb_hash_merge, 1); + rb_define_method(rb_cHash, "merge!", rb_hash_update, -1); + rb_define_method(rb_cHash, "merge", rb_hash_merge, -1); rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1); rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1); rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1); diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index 088178defa..11735c5620 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -1123,11 +1123,35 @@ class TestHash < Test::Unit::TestCase assert_equal({1=>6, 3=>4, 5=>7}, h1) end + def test_update3 + h1 = @cls[1=>2, 3=>4] + h1.update() + assert_equal({1=>2, 3=>4}, h1) + h2 = {1=>3, 5=>7} + h3 = {1=>1, 2=>4} + h1.update(h2, h3) + assert_equal({1=>1, 2=>4, 3=>4, 5=>7}, h1) + end + + def test_update4 + h1 = @cls[1=>2, 3=>4] + h1.update(){|k, v1, v2| k + v1 + v2 } + assert_equal({1=>2, 3=>4}, h1) + h2 = {1=>3, 5=>7} + h3 = {1=>1, 2=>4} + h1.update(h2, h3){|k, v1, v2| k + v1 + v2 } + assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1) + end + def test_merge h1 = @cls[1=>2, 3=>4] h2 = {1=>3, 5=>7} + h3 = {1=>1, 2=>4} + assert_equal({1=>2, 3=>4}, h1.merge()) assert_equal({1=>3, 3=>4, 5=>7}, h1.merge(h2)) assert_equal({1=>6, 3=>4, 5=>7}, h1.merge(h2) {|k, v1, v2| k + v1 + v2 }) + assert_equal({1=>1, 2=>4, 3=>4, 5=>7}, h1.merge(h2, h3)) + assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1.merge(h2, h3) {|k, v1, v2| k + v1 + v2 }) end def test_assoc |