Skip to content

Commit 085f5ef

Browse files
committed
* hash.c (rb_hash_merge): Accepts zero or more hashes as arguments
Hash#merge, merge!, and update could merge exactly two hashes. Now, they accepts zero or more hashes as arguments so that it can merge hashes more than two. This patch was created by Koki Ryu <liukoki@gmail.com> at Ruby Hack Challenge #5. Thank you! [ruby-core:88970] [Feature ruby#15111] [Fix rubyGH-1951] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64777 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent a4675d9 commit 085f5ef

File tree

2 files changed

+86
-32
lines changed

2 files changed

+86
-32
lines changed

hash.c

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,16 +2548,23 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
25482548

25492549
/*
25502550
* call-seq:
2551-
* hsh.merge!(other_hash) -> hsh
2552-
* hsh.update(other_hash) -> hsh
2553-
* hsh.merge!(other_hash){|key, oldval, newval| block} -> hsh
2554-
* hsh.update(other_hash){|key, oldval, newval| block} -> hsh
2555-
*
2556-
* Adds the contents of _other_hash_ to _hsh_. If no block is specified,
2557-
* entries with duplicate keys are overwritten with the values from
2558-
* _other_hash_, otherwise the value of each duplicate key is determined by
2551+
* hsh.merge!(other_hash1, other_hash2, ...) -> hsh
2552+
* hsh.update(other_hash1, other_hash2, ...) -> hsh
2553+
* hsh.merge!(other_hash1, other_hash2, ...){|key, oldval, newval| block}
2554+
* -> hsh
2555+
* hsh.update(other_hash1, other_hash2, ...){|key, oldval, newval| block}
2556+
* -> hsh
2557+
*
2558+
* Adds the contents of _other_hash_s to _hsh_ repeatedly. If no block is
2559+
* specified, entries with duplicate keys are overwritten with the values from
2560+
* each _other_hash_, otherwise the value of each duplicate key is determined by
25592561
* calling the block with the key, its value in _hsh_ and its value in
2560-
* _other_hash_.
2562+
* each _other_hash_. The method also can be called with no argument,
2563+
* then nothing will change in the receiver.
2564+
*
2565+
* h1 = { "a" => 100, "b" => 200 }
2566+
* h1.merge!() #=> {"a"=>100, "b"=>200}
2567+
* h1 #=> {"a"=>100, "b"=>200}
25612568
*
25622569
* h1 = { "a" => 100, "b" => 200 }
25632570
* h2 = { "b" => 254, "c" => 300 }
@@ -2566,23 +2573,36 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
25662573
*
25672574
* h1 = { "a" => 100, "b" => 200 }
25682575
* h2 = { "b" => 254, "c" => 300 }
2569-
* h1.merge!(h2) { |key, v1, v2| v1 }
2570-
* #=> {"a"=>100, "b"=>200, "c"=>300}
2571-
* h1 #=> {"a"=>100, "b"=>200, "c"=>300}
2576+
* h3 = { "b" => 100, "d" => 400 }
2577+
* h1.merge!(h2, h3)
2578+
* #=> {"a"=>100, "b"=>100, "c"=>300, "d"=>400}
2579+
* h1 #=> {"a"=>100, "b"=>100, "c"=>300, "d"=>400}
2580+
*
2581+
* h1 = { "a" => 100, "b" => 200 }
2582+
* h2 = { "b" => 254, "c" => 300 }
2583+
* h3 = { "b" => 100, "d" => 400 }
2584+
* h1.merge!(h2, h3) { |key, v1, v2| v1 }
2585+
* #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}
2586+
* h1 #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}
25722587
*/
25732588

25742589
static VALUE
2575-
rb_hash_update(VALUE hash1, VALUE hash2)
2590+
rb_hash_update(int argc, VALUE *argv, VALUE self)
25762591
{
2577-
rb_hash_modify(hash1);
2578-
hash2 = to_hash(hash2);
2579-
if (rb_block_given_p()) {
2580-
rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
2581-
}
2582-
else {
2583-
rb_hash_foreach(hash2, rb_hash_update_i, hash1);
2592+
int i;
2593+
bool block_given = rb_block_given_p();
2594+
2595+
rb_hash_modify(self);
2596+
for (i = 0; i < argc; i++){
2597+
VALUE hash = to_hash(argv[i]);
2598+
if (block_given) {
2599+
rb_hash_foreach(hash, rb_hash_update_block_i, self);
2600+
}
2601+
else {
2602+
rb_hash_foreach(hash, rb_hash_update_i, self);
2603+
}
25842604
}
2585-
return hash1;
2605+
return self;
25862606
}
25872607

25882608
struct update_func_arg {
@@ -2641,28 +2661,38 @@ rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
26412661

26422662
/*
26432663
* call-seq:
2644-
* hsh.merge(other_hash) -> new_hash
2645-
* hsh.merge(other_hash){|key, oldval, newval| block} -> new_hash
2664+
* hsh.merge(other_hash1, other_hash2, ...) -> new_hash
2665+
* hsh.merge(other_hash1, other_hash2, ...){|key, oldval, newval| block}
2666+
* -> new_hash
26462667
*
2647-
* Returns a new hash containing the contents of <i>other_hash</i> and
2668+
* Returns a new hash containing the contents of <i>other_hash</i>s and
26482669
* the contents of <i>hsh</i>. If no block is specified, the value for
2649-
* entries with duplicate keys will be that of <i>other_hash</i>. Otherwise
2650-
* the value for each duplicate key is determined by calling the block
2651-
* with the key, its value in <i>hsh</i> and its value in <i>other_hash</i>.
2670+
* entries with duplicate keys will be that of each <i>other_hash</i>.
2671+
* Otherwise the value for each duplicate key is determined by calling
2672+
* the block with the key, its value in <i>hsh</i> and its value
2673+
* in each <i>other_hash</i>. The method also can be called with no argument,
2674+
* then a new hash, whose content is same as that of the receiver,
2675+
* will be returned;
26522676
*
26532677
* h1 = { "a" => 100, "b" => 200 }
26542678
* h2 = { "b" => 254, "c" => 300 }
2679+
* h3 = { "b" => 100, "d" => 400 }
2680+
* h1.merge() #=> {"a"=>100, "b"=>200}
26552681
* h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
2682+
* h1.merge(h2, h3)
2683+
* #=> {"a"=>100, "b"=>100, "c"=>300, "d"=>400}
26562684
* h1.merge(h2){|key, oldval, newval| newval - oldval}
26572685
* #=> {"a"=>100, "b"=>54, "c"=>300}
2686+
* h1.merge(h2, h3){|key, oldval, newval| newval - oldval}
2687+
* #=> {"a"=>100, "b"=>46, "c"=>300, "d"=>400}
26582688
* h1 #=> {"a"=>100, "b"=>200}
26592689
*
26602690
*/
26612691

26622692
static VALUE
2663-
rb_hash_merge(VALUE hash1, VALUE hash2)
2693+
rb_hash_merge(int argc, VALUE *argv, VALUE self)
26642694
{
2665-
return rb_hash_update(rb_hash_dup(hash1), hash2);
2695+
return rb_hash_update(argc, argv, rb_hash_dup(self));
26662696
}
26672697

26682698
static int
@@ -4761,10 +4791,10 @@ Init_Hash(void)
47614791
rb_define_method(rb_cHash, "slice", rb_hash_slice, -1);
47624792
rb_define_method(rb_cHash, "clear", rb_hash_clear, 0);
47634793
rb_define_method(rb_cHash, "invert", rb_hash_invert, 0);
4764-
rb_define_method(rb_cHash, "update", rb_hash_update, 1);
4794+
rb_define_method(rb_cHash, "update", rb_hash_update, -1);
47654795
rb_define_method(rb_cHash, "replace", rb_hash_replace, 1);
4766-
rb_define_method(rb_cHash, "merge!", rb_hash_update, 1);
4767-
rb_define_method(rb_cHash, "merge", rb_hash_merge, 1);
4796+
rb_define_method(rb_cHash, "merge!", rb_hash_update, -1);
4797+
rb_define_method(rb_cHash, "merge", rb_hash_merge, -1);
47684798
rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1);
47694799
rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1);
47704800
rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1);

test/ruby/test_hash.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,11 +1123,35 @@ def test_update2
11231123
assert_equal({1=>6, 3=>4, 5=>7}, h1)
11241124
end
11251125

1126+
def test_update3
1127+
h1 = @cls[1=>2, 3=>4]
1128+
h1.update()
1129+
assert_equal({1=>2, 3=>4}, h1)
1130+
h2 = {1=>3, 5=>7}
1131+
h3 = {1=>1, 2=>4}
1132+
h1.update(h2, h3)
1133+
assert_equal({1=>1, 2=>4, 3=>4, 5=>7}, h1)
1134+
end
1135+
1136+
def test_update4
1137+
h1 = @cls[1=>2, 3=>4]
1138+
h1.update(){|k, v1, v2| k + v1 + v2 }
1139+
assert_equal({1=>2, 3=>4}, h1)
1140+
h2 = {1=>3, 5=>7}
1141+
h3 = {1=>1, 2=>4}
1142+
h1.update(h2, h3){|k, v1, v2| k + v1 + v2 }
1143+
assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1)
1144+
end
1145+
11261146
def test_merge
11271147
h1 = @cls[1=>2, 3=>4]
11281148
h2 = {1=>3, 5=>7}
1149+
h3 = {1=>1, 2=>4}
1150+
assert_equal({1=>2, 3=>4}, h1.merge())
11291151
assert_equal({1=>3, 3=>4, 5=>7}, h1.merge(h2))
11301152
assert_equal({1=>6, 3=>4, 5=>7}, h1.merge(h2) {|k, v1, v2| k + v1 + v2 })
1153+
assert_equal({1=>1, 2=>4, 3=>4, 5=>7}, h1.merge(h2, h3))
1154+
assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1.merge(h2, h3) {|k, v1, v2| k + v1 + v2 })
11311155
end
11321156

11331157
def test_assoc

0 commit comments

Comments
 (0)