Feature #14788 ยป hash_keys_block.patch
| hash.c | ||
|---|---|---|
| 
         return ST_CONTINUE; 
   | 
||
| 
     } 
   | 
||
| 
     static int 
   | 
||
| 
     keys_block_i(VALUE key, VALUE value, VALUE ary) 
   | 
||
| 
     { 
   | 
||
| 
         if (RTEST(rb_yield(key))) { 
   | 
||
| 
             rb_ary_push(ary, key); 
   | 
||
| 
         } 
   | 
||
| 
         return ST_CONTINUE; 
   | 
||
| 
     } 
   | 
||
| 
     /* 
   | 
||
| 
      *  call-seq: 
   | 
||
| 
      *     hsh.keys    -> array 
   | 
||
| 
      * 
   | 
||
| 
      *  Returns a new array populated with the keys from this hash. See also 
   | 
||
| 
      *  <code>Hash#values</code>. 
   | 
||
| 
      *  <code>Hash#values</code>. If a block is given, it returns the keys for 
   | 
||
| 
      *  which the block evaluates to +true+. 
   | 
||
| 
      * 
   | 
||
| 
      *     h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 } 
   | 
||
| 
      *     h.keys   #=> ["a", "b", "c", "d"] 
   | 
||
| 
      *     h.keys                                 #=> ["a", "b", "c", "d"] 
   | 
||
| 
      #     h.keys { |key| %w[a c].include?(key) } #=> ["a", "c"] 
   | 
||
| 
      * 
   | 
||
| 
      */ 
   | 
||
| ... | ... | |
| 
         st_index_t size = RHASH_SIZE(hash); 
   | 
||
| 
         keys = rb_ary_new_capa(size); 
   | 
||
| 
         if (size == 0) return keys; 
   | 
||
| 
         if (ST_DATA_COMPATIBLE_P(VALUE)) { 
   | 
||
| 
     	st_table *table = RHASH(hash)->ntbl; 
   | 
||
| 
         if (size == 0) return keys; 
   | 
||
| 
     	rb_gc_writebarrier_remember(keys); 
   | 
||
| 
     	RARRAY_PTR_USE(keys, ptr, { 
   | 
||
| 
     	    size = st_keys(table, ptr, size); 
   | 
||
| 
     	}); 
   | 
||
| 
     	rb_ary_set_len(keys, size); 
   | 
||
| 
         if (rb_block_given_p()) { 
   | 
||
| 
             rb_hash_foreach(hash, keys_block_i, keys); 
   | 
||
| 
         } 
   | 
||
| 
         else { 
   | 
||
| 
     	rb_hash_foreach(hash, keys_i, keys); 
   | 
||
| 
             if (ST_DATA_COMPATIBLE_P(VALUE)) { 
   | 
||
| 
                 st_table *table = RHASH(hash)->ntbl; 
   | 
||
| 
                 rb_gc_writebarrier_remember(keys); 
   | 
||
| 
                 RARRAY_PTR_USE(keys, ptr, { 
   | 
||
| 
                     size = st_keys(table, ptr, size); 
   | 
||
| 
                 }); 
   | 
||
| 
                 rb_ary_set_len(keys, size); 
   | 
||
| 
             } 
   | 
||
| 
             else { 
   | 
||
| 
                 rb_hash_foreach(hash, keys_i, keys); 
   | 
||
| 
             } 
   | 
||
| 
         } 
   | 
||
| 
         return keys; 
   | 
||
| spec/ruby/core/hash/keys_spec.rb | ||
|---|---|---|
| 
           h[h.keys[i]].should == h.values[i] 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       it "accepts a block" do 
   | 
||
| 
         h = { 1 => "1", 2 => "2", 3 => "3", 4 => "4" } 
   | 
||
| 
         h.keys { |key| key.odd?  }.should == [1, 3] 
   | 
||
| 
         h.keys { |key| key.even? }.should == [2, 4] 
   | 
||
| 
       end 
   | 
||
| 
     end 
   | 
||