mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	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:
		
							parent
							
								
									cb18d4ba46
								
							
						
					
					
						commit
						ea5184b939
					
				
					 3 changed files with 95 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -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(*)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue