Feature #9970 ยป hash-map-keys-and-map-values.diff
hash.c (working copy) | ||
---|---|---|
return Qfalse;
|
||
}
|
||
VALUE
|
||
map_hash(VALUE hash, int (*func)(ANYARGS))
|
||
{
|
||
VALUE result;
|
||
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
|
||
result = rb_hash_new();
|
||
if (!RHASH_EMPTY_P(hash)) {
|
||
rb_hash_foreach(hash, func, result);
|
||
}
|
||
return result;
|
||
}
|
||
static int
|
||
map_keys_i(VALUE key, VALUE value, VALUE result)
|
||
{
|
||
rb_hash_aset(result, rb_yield(key), value);
|
||
return ST_CONTINUE;
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* hsh.map_keys {| key | block } -> a_hash
|
||
* hsh.map_keys -> an_enumerator
|
||
*
|
||
* Returns a new hash, with the keys computed from running <code>block<code>
|
||
* once for each key in the hash, and the values unchanged.
|
||
*
|
||
* If no block is given, an enumerator is returned instead.
|
||
*
|
||
* h = { "a" => 100, "b" => 200 }
|
||
* h.map_keys { |key| key + '!' } #=> { "a!" => 100, "b!" => 200 }
|
||
*
|
||
*/
|
||
VALUE
|
||
rb_hash_map_keys(VALUE hash)
|
||
{
|
||
return map_hash(hash, map_keys_i);
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* hsh.map_keys! {| key | block } -> hsh or nil
|
||
* hsh.map_keys! -> an_enumerator
|
||
*
|
||
* Replaces every key in the hash with the result of calling <code>block</code>
|
||
* once for each key in the hash. Returns <code>nil</code> if no changes were made.
|
||
*
|
||
* If no block is given, an enumerator is returned instead.
|
||
*
|
||
* h = { "a" => 100, "b" => 200 }
|
||
* h.map_keys! { |key| key + '!' } #=> { "a!" => 100, "b!" => 200 }
|
||
*
|
||
*/
|
||
VALUE
|
||
rb_hash_map_keys_bang(VALUE hash)
|
||
{
|
||
st_index_t n;
|
||
VALUE keys;
|
||
long i;
|
||
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
|
||
rb_hash_modify(hash);
|
||
n = RHASH_SIZE(hash);
|
||
if (!n) return Qnil;
|
||
keys = rb_hash_keys(hash);
|
||
for (i = 0; i < RARRAY_LEN(keys); i++) {
|
||
VALUE key = RARRAY_AREF(keys, i);
|
||
rb_hash_aset(hash, rb_yield(key), rb_hash_delete(hash, key));
|
||
}
|
||
return hash;
|
||
}
|
||
static int
|
||
map_values_i(VALUE key, VALUE value, VALUE result)
|
||
{
|
||
rb_hash_aset(result, key, rb_yield(value));
|
||
return ST_CONTINUE;
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* hsh.map_values {| value | block } -> a_hash
|
||
* hsh.map_values -> an_enumerator
|
||
*
|
||
* Returns a new hash, with the values computed from running <code>block<code>
|
||
* once for each value in the hash, and the values unchanged.
|
||
*
|
||
* If no block is given, an enumerator is returned instead.
|
||
*
|
||
* h = { "a" => 100, "b" => 200 }
|
||
* h.map_values { |value| value * 2 } #=> { "a" => 200, "b" => 400 }
|
||
*
|
||
*/
|
||
VALUE
|
||
rb_hash_map_values(VALUE hash)
|
||
{
|
||
return map_hash(hash, map_values_i);
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* hsh.map_values! {| value | block } -> hsh or nil
|
||
* hsh.map_values! -> an_enumerator
|
||
*
|
||
* Replaces every value in the hash with the result of calling <code>block</code>
|
||
* once for each value in the hash, and the keys unchanged.
|
||
*
|
||
* If no block is given, an enumerator is returned instead.
|
||
*
|
||
* h = { "a" => 100, "b" => 200 }
|
||
* h.map_values! { |value| value * 2 } #=> { "a" => 200, "b" => 400 }
|
||
*
|
||
*/
|
||
VALUE
|
||
rb_hash_map_values_bang(VALUE hash)
|
||
{
|
||
st_index_t n;
|
||
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
|
||
n = RHASH_SIZE(hash);
|
||
if (!n) return Qnil;
|
||
rb_hash_foreach(hash, map_values_i, hash);
|
||
return hash;
|
||
}
|
||
static int path_tainted = -1;
|
||
static char **origenviron;
|
||
... | ... | |
rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1);
|
||
rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1);
|
||
rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1);
|
||
rb_define_method(rb_cHash, "map_keys", rb_hash_map_keys, 0);
|
||
rb_define_method(rb_cHash, "map_keys!", rb_hash_map_keys_bang, 0);
|
||
rb_define_method(rb_cHash, "map_values", rb_hash_map_values, 0);
|
||
rb_define_method(rb_cHash, "map_values!", rb_hash_map_values_bang, 0);
|
||
rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1);
|
||
rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1);
|
test/ruby/test_hash.rb (working copy) | ||
---|---|---|
assert_equal(bug9381, hash[wrapper.new(5)])
|
||
end
|
||
def test_map_keys
|
||
original = { 'a' => 'a', 'b' => 'b' }
|
||
mapped = original.map_keys { |key| key + '!' }
|
||
assert_equal({ 'a' => 'a', 'b' => 'b' }, original)
|
||
assert_equal({ 'a!' => 'a', 'b!' => 'b' }, mapped)
|
||
end
|
||
def test_map_keys_bang
|
||
original = { 'a' => 'a', 'b' => 'b' }
|
||
mapped = original.map_keys! { |key| key + '!' }
|
||
assert_equal({ 'a!' => 'a', 'b!' => 'b' }, original)
|
||
assert_equal({ 'a!' => 'a', 'b!' => 'b' }, mapped)
|
||
end
|
||
def test_map_keys_bang_on_empty_hash
|
||
original = {}
|
||
mapped = original.map_keys! { |key| key + '!' }
|
||
assert_equal({}, original)
|
||
assert_nil mapped
|
||
end
|
||
def test_map_values
|
||
original = { 'a' => 'a', 'b' => 'b' }
|
||
mapped = original.map_values { |value| value + '!' }
|
||
assert_equal({ 'a' => 'a', 'b' => 'b' }, original)
|
||
assert_equal({ 'a' => 'a!', 'b' => 'b!' }, mapped)
|
||
end
|
||
def test_map_values_bang
|
||
original = { 'a' => 'a', 'b' => 'b' }
|
||
mapped = original.map_values! { |value| value + '!' }
|
||
assert_equal({ 'a' => 'a!', 'b' => 'b!' }, original)
|
||
assert_equal({ 'a' => 'a!', 'b' => 'b!' }, mapped)
|
||
end
|
||
def test_map_values_bang_on_empty_hash
|
||
original = {}
|
||
mapped = original.map_values! { |value| value + '!' }
|
||
assert_equal({}, original)
|
||
assert_nil mapped
|
||
end
|
||
class TestSubHash < TestHash
|
||
class SubHash < Hash
|
||
def reject(*)
|