Project

General

Profile

Feature #14788 ยป hash_keys_block.patch

rringler (Ryan Ringler), 05/28/2018 06:13 AM

View differences:

hash.c
2143 2143
    return ST_CONTINUE;
2144 2144
}
2145 2145

  
2146
static int
2147
keys_block_i(VALUE key, VALUE value, VALUE ary)
2148
{
2149
    if (RTEST(rb_yield(key))) {
2150
        rb_ary_push(ary, key);
2151
    }
2152
    return ST_CONTINUE;
2153
}
2154

  
2146 2155
/*
2147 2156
 *  call-seq:
2148 2157
 *     hsh.keys    -> array
2149 2158
 *
2150 2159
 *  Returns a new array populated with the keys from this hash. See also
2151
 *  <code>Hash#values</code>.
2160
 *  <code>Hash#values</code>. If a block is given, it returns the keys for
2161
 *  which the block evaluates to +true+.
2152 2162
 *
2153 2163
 *     h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
2154
 *     h.keys   #=> ["a", "b", "c", "d"]
2164
 *     h.keys                                 #=> ["a", "b", "c", "d"]
2165
 #     h.keys { |key| %w[a c].include?(key) } #=> ["a", "c"]
2155 2166
 *
2156 2167
 */
2157 2168

  
......
2162 2173
    st_index_t size = RHASH_SIZE(hash);
2163 2174

  
2164 2175
    keys = rb_ary_new_capa(size);
2165
    if (size == 0) return keys;
2166 2176

  
2167
    if (ST_DATA_COMPATIBLE_P(VALUE)) {
2168
	st_table *table = RHASH(hash)->ntbl;
2177
    if (size == 0) return keys;
2169 2178

  
2170
	rb_gc_writebarrier_remember(keys);
2171
	RARRAY_PTR_USE(keys, ptr, {
2172
	    size = st_keys(table, ptr, size);
2173
	});
2174
	rb_ary_set_len(keys, size);
2179
    if (rb_block_given_p()) {
2180
        rb_hash_foreach(hash, keys_block_i, keys);
2175 2181
    }
2176 2182
    else {
2177
	rb_hash_foreach(hash, keys_i, keys);
2183
        if (ST_DATA_COMPATIBLE_P(VALUE)) {
2184
            st_table *table = RHASH(hash)->ntbl;
2185

  
2186
            rb_gc_writebarrier_remember(keys);
2187

  
2188
            RARRAY_PTR_USE(keys, ptr, {
2189
                size = st_keys(table, ptr, size);
2190
            });
2191

  
2192
            rb_ary_set_len(keys, size);
2193
        }
2194
        else {
2195
            rb_hash_foreach(hash, keys_i, keys);
2196
        }
2178 2197
    }
2179 2198

  
2180 2199
    return keys;
spec/ruby/core/hash/keys_spec.rb
20 20
      h[h.keys[i]].should == h.values[i]
21 21
    end
22 22
  end
23

  
24
  it "accepts a block" do
25
    h = { 1 => "1", 2 => "2", 3 => "3", 4 => "4" }
26

  
27
    h.keys { |key| key.odd?  }.should == [1, 3]
28
    h.keys { |key| key.even? }.should == [2, 4]
29
  end
23 30
end