ruby-changes:44341
From: nobu <ko1@a...>
Date: Thu, 13 Oct 2016 17:06:15 +0900 (JST)
Subject: [ruby-changes:44341] nobu:r56414 (trunk): hash.c: add compact and compact! methods
nobu 2016-10-13 17:06:00 +0900 (Thu, 13 Oct 2016) New Revision: 56414 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=56414 Log: hash.c: add compact and compact! methods * hash.c (rb_hash_compact, rb_hash_compact_bang): Removes nil values from the original hash, to port Active Support behavior. [Feature #11818] Modified files: trunk/ChangeLog trunk/hash.c trunk/test/ruby/test_hash.rb Index: test/ruby/test_hash.rb =================================================================== --- test/ruby/test_hash.rb (revision 56413) +++ test/ruby/test_hash.rb (revision 56414) @@ -354,6 +354,14 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L354 assert_equal({1=>2,3=>4,5=>6}, h.keep_if{true}) end + def test_compact + h = @cls[a: 1, b: nil, c: false, d: true, e: nil] + assert_equal({a: 1, c: false, d: true}, h.compact) + assert_equal({a: 1, b: nil, c: false, d: true, e: nil}, h) + h.compact! + assert_equal({a: 1, c: false, d: true}, h) + end + def test_dup for taint in [ false, true ] for frozen in [ false, true ] Index: hash.c =================================================================== --- hash.c (revision 56413) +++ hash.c (revision 56414) @@ -2669,6 +2669,68 @@ rb_hash_flatten(int argc, VALUE *argv, V https://github.com/ruby/ruby/blob/trunk/hash.c#L2669 return ary; } +static int +delete_if_nil(VALUE key, VALUE value, VALUE hash) +{ + if (NIL_P(value)) { + return ST_DELETE; + } + return ST_CONTINUE; +} + +static int +set_if_not_nil(VALUE key, VALUE value, VALUE hash) +{ + if (!NIL_P(value)) { + rb_hash_aset(hash, key, value); + } + return ST_CONTINUE; +} + +/* + * call-seq: + * hsh.compact -> new_hash + * + * Returns a new hash with the nil values/key pairs removed + * + * h = { a: 1, b: false, c: nil } + * h.compact #=> { a: 1, b: false } + * h #=> { a: 1, b: false, c: nil } + * + */ + +static VALUE +rb_hash_compact(VALUE hash) +{ + VALUE result = rb_hash_new(); + if (!RHASH_EMPTY_P(hash)) { + rb_hash_foreach(hash, set_if_not_nil, result); + } + return result; +} + +/* + * call-seq: + * hsh.compact! -> hsh + * + * Removes all nil values from the hash. + * Returns the hash. + * + * h = { a: 1, b: false, c: nil } + * h.compact! #=> { a: 1, b: false } + * + */ + +static VALUE +rb_hash_compact_bang(VALUE hash) +{ + rb_hash_modify_check(hash); + if (RHASH(hash)->ntbl) { + rb_hash_foreach(hash, delete_if_nil, hash); + } + return hash; +} + static VALUE rb_hash_compare_by_id_p(VALUE hash); /* @@ -4426,6 +4488,8 @@ Init_Hash(void) https://github.com/ruby/ruby/blob/trunk/hash.c#L4488 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,"compact", rb_hash_compact, 0); + rb_define_method(rb_cHash,"compact!", rb_hash_compact_bang, 0); rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1); rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1); Index: ChangeLog =================================================================== --- ChangeLog (revision 56413) +++ ChangeLog (revision 56414) @@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Oct 13 17:05:57 2016 Dwain Faithfull <dwfaithfull@g...> + + * hash.c (rb_hash_compact, rb_hash_compact_bang): Removes nil + values from the original hash, to port Active Support behavior. + [Feature #11818] + Thu Oct 13 11:35:33 2016 Nobuyoshi Nakada <nobu@r...> * array.c (rb_ary_sort_bang, rb_ary_sort, rb_ary_sort_by_bang): -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/