зеркало из https://github.com/github/ruby.git
hash.c: implement Hash#map_v and Hash#map_v!
* hash.c (rb_hash_map_v, rb_hash_map_v_bang): impelement Hash#map_v and Hash#map_v! [Feature #12512] [ruby-core:76095] * test/ruby/test_hash.rb: add tests for above change. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55847 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
cb18d4ba46
Коммит
ea5184b939
|
@ -1,3 +1,10 @@
|
|||
Tue Aug 9 17:50:00 2016 Kenta Murata <mrkn@mrkn.jp>
|
||||
|
||||
* hash.c (rb_hash_map_v, rb_hash_map_v_bang): impelement Hash#map_v and
|
||||
Hash#map_v! [Feature #12512] [ruby-core:76095]
|
||||
|
||||
* test/ruby/test_hash.rb: add tests for above change.
|
||||
|
||||
Tue Aug 9 16:09:03 2016 NARUSE, Yui <naruse@ruby-lang.org>
|
||||
|
||||
* vm_insnhelper.c (vm_getivar): use always_inline because
|
||||
|
|
67
hash.c
67
hash.c
|
@ -1787,6 +1787,70 @@ rb_hash_each_pair(VALUE hash)
|
|||
return hash;
|
||||
}
|
||||
|
||||
static int
|
||||
map_v_i(VALUE key, VALUE value, VALUE result)
|
||||
{
|
||||
VALUE new_value = rb_yield(value);
|
||||
rb_hash_aset(result, key, new_value);
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* hsh.map_v {|value| block } -> hsh
|
||||
* hsh.map_v -> an_enumerator
|
||||
*
|
||||
* Return a new with the results of running block once for every value.
|
||||
* This method does not change the keys.
|
||||
*
|
||||
* h = { a: 1, b: 2, c: 3 }
|
||||
* h.map_v {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 }
|
||||
* h.map_v(&:to_s) #=> { a: "1", b: "2", c: "3" }
|
||||
* h.map_v.with_index {|v, i| "#{v}.#{i}" }
|
||||
* #=> { a: "1.0", b: "2.1", c: "3.2" }
|
||||
*
|
||||
* If no block is given, an enumerator is returned instead.
|
||||
*/
|
||||
static VALUE
|
||||
rb_hash_map_v(VALUE hash)
|
||||
{
|
||||
VALUE result;
|
||||
|
||||
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
|
||||
result = rb_hash_new();
|
||||
if (!RHASH_EMPTY_P(hash)) {
|
||||
rb_hash_foreach(hash, map_v_i, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* hsh.map_v! {|value| block } -> hsh
|
||||
* hsh.map_v! -> an_enumerator
|
||||
*
|
||||
* Return a new with the results of running block once for every value.
|
||||
* This method does not change the keys.
|
||||
*
|
||||
* h = { a: 1, b: 2, c: 3 }
|
||||
* h.map_v! {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 }
|
||||
* h.map_v!(&:to_s) #=> { a: "1", b: "2", c: "3" }
|
||||
* h.map_v!.with_index {|v, i| "#{v}.#{i}" }
|
||||
* #=> { a: "1.0", b: "2.1", c: "3.2" }
|
||||
*
|
||||
* If no block is given, an enumerator is returned instead.
|
||||
*/
|
||||
static VALUE
|
||||
rb_hash_map_v_bang(VALUE hash)
|
||||
{
|
||||
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
|
||||
rb_hash_modify_check(hash);
|
||||
if (RHASH(hash)->ntbl)
|
||||
rb_hash_foreach(hash, map_v_i, hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
static int
|
||||
to_a_i(VALUE key, VALUE value, VALUE ary)
|
||||
{
|
||||
|
@ -4336,6 +4400,9 @@ Init_Hash(void)
|
|||
rb_define_method(rb_cHash,"each_pair", rb_hash_each_pair, 0);
|
||||
rb_define_method(rb_cHash,"each", rb_hash_each_pair, 0);
|
||||
|
||||
rb_define_method(rb_cHash, "map_v", rb_hash_map_v, 0);
|
||||
rb_define_method(rb_cHash, "map_v!", rb_hash_map_v_bang, 0);
|
||||
|
||||
rb_define_method(rb_cHash,"keys", rb_hash_keys, 0);
|
||||
rb_define_method(rb_cHash,"values", rb_hash_values, 0);
|
||||
rb_define_method(rb_cHash,"values_at", rb_hash_values_at, -1);
|
||||
|
|
|
@ -1415,6 +1415,27 @@ class TestHash < Test::Unit::TestCase
|
|||
assert_equal([10, 20, 30], [1, 2, 3].map(&h))
|
||||
end
|
||||
|
||||
def test_map_v
|
||||
x = @cls[a: 1, b: 2, c: 3]
|
||||
y = x.map_v {|v| v ** 2 }
|
||||
assert_equal([1, 4, 9], y.values_at(:a, :b, :c))
|
||||
assert_not_same(x, y)
|
||||
|
||||
y = x.map_v.with_index {|v, i| "#{v}.#{i}" }
|
||||
assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c))
|
||||
end
|
||||
|
||||
def test_map_v_bang
|
||||
x = @cls[a: 1, b: 2, c: 3]
|
||||
y = x.map_v! {|v| v ** 2 }
|
||||
assert_equal([1, 4, 9], y.values_at(:a, :b, :c))
|
||||
assert_same(x, y)
|
||||
|
||||
x = @cls[a: 1, b: 2, c: 3]
|
||||
y = x.map_v!.with_index {|v, i| "#{v}.#{i}" }
|
||||
assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c))
|
||||
end
|
||||
|
||||
class TestSubHash < TestHash
|
||||
class SubHash < Hash
|
||||
def reject(*)
|
||||
|
|
Загрузка…
Ссылка в новой задаче