diff options
author | Marc-Andre Lafortune <[email protected]> | 2021-03-15 23:51:13 -0400 |
---|---|---|
committer | Marc-Andre Lafortune <[email protected]> | 2021-03-18 07:34:40 -0400 |
commit | d094c3ef046aba0bb99fd08bcbc72ff87216e736 (patch) | |
tree | 08986627bc91061cf33259de1d8059553f289d3c /hash.c | |
parent | 85f99f4b715a5954124d5014002c16652995b128 (diff) |
Avoid rehashing in Hash#select/reject [Bug #16996]
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 32 |
1 files changed, 7 insertions, 25 deletions
@@ -2547,15 +2547,6 @@ rb_hash_reject_bang(VALUE hash) return hash; } -static int -reject_i(VALUE key, VALUE value, VALUE result) -{ - if (!RTEST(rb_yield_values(2, key, value))) { - rb_hash_aset(result, key, value); - } - return ST_CONTINUE; -} - /* * call-seq: * hash.reject {|key, value| ... } -> new_hash @@ -2586,9 +2577,9 @@ rb_hash_reject(VALUE hash) rb_warn("extra states are no longer copied: %+"PRIsVALUE, hash); } } - result = rb_hash_new(); + result = hash_copy(hash_alloc(rb_cHash), hash); if (!RHASH_EMPTY_P(hash)) { - rb_hash_foreach(hash, reject_i, result); + rb_hash_foreach(result, delete_if_i, result); } return result; } @@ -2711,10 +2702,10 @@ rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash) } static int -select_i(VALUE key, VALUE value, VALUE result) +keep_if_i(VALUE key, VALUE value, VALUE hash) { - if (RTEST(rb_yield_values(2, key, value))) { - rb_hash_aset(result, key, value); + if (!RTEST(rb_yield_values(2, key, value))) { + return ST_DELETE; } return ST_CONTINUE; } @@ -2742,22 +2733,13 @@ rb_hash_select(VALUE hash) VALUE result; RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); - result = rb_hash_new(); + result = hash_copy(hash_alloc(rb_cHash), hash); if (!RHASH_EMPTY_P(hash)) { - rb_hash_foreach(hash, select_i, result); + rb_hash_foreach(result, keep_if_i, result); } return result; } -static int -keep_if_i(VALUE key, VALUE value, VALUE hash) -{ - if (!RTEST(rb_yield_values(2, key, value))) { - return ST_DELETE; - } - return ST_CONTINUE; -} - /* * call-seq: * hash.select! {|key, value| ... } -> self or nil |