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
|