ruby-changes:14932
From: matz <ko1@a...>
Date: Wed, 3 Mar 2010 18:45:05 +0900 (JST)
Subject: [ruby-changes:14932] Ruby:r26803 (trunk): * hash.c (rb_hash_select_bang): add #select! and keep_if to Hash.
matz 2010-03-03 18:44:44 +0900 (Wed, 03 Mar 2010) New Revision: 26803 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=26803 Log: * hash.c (rb_hash_select_bang): add #select! and keep_if to Hash. * hash.c (env_select_bang): ..and to ENV. Modified files: trunk/ChangeLog trunk/hash.c trunk/test/ruby/test_hash.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 26802) +++ ChangeLog (revision 26803) @@ -1,3 +1,9 @@ +Wed Mar 3 18:35:55 2010 Yukihiro Matsumoto <matz@r...> + + * hash.c (rb_hash_select_bang): add #select! and keep_if to Hash. + + * hash.c (env_select_bang): ..and to ENV. + Wed Mar 3 15:54:20 2010 Yukihiro Matsumoto <matz@r...> * lib/matrix.rb (Vector#each2, collect2): small refactoring. Index: hash.c =================================================================== --- hash.c (revision 26802) +++ hash.c (revision 26803) @@ -990,6 +990,57 @@ } static int +keep_if_i(VALUE key, VALUE value, VALUE hash) +{ + if (key == Qundef) return ST_CONTINUE; + if (!RTEST(rb_yield_values(2, key, value))) { + return ST_DELETE; + } + return ST_CONTINUE; +} + +/* + * call-seq: + * hsh.select! {| key, value | block } -> hsh or nil + * + * Equivalent to <code>Hash#keep_if</code>, but returns + * <code>nil</code> if no changes were made. + */ + +VALUE +rb_hash_select_bang(VALUE hash) +{ + st_index_t n; + + RETURN_ENUMERATOR(hash, 0, 0); + rb_hash_modify(hash); + if (!RHASH(hash)->ntbl) + return Qnil; + n = RHASH(hash)->ntbl->num_entries; + rb_hash_foreach(hash, keep_if_i, hash); + if (n == RHASH(hash)->ntbl->num_entries) return Qnil; + return hash; +} + +/* + * call-seq: + * hsh.keep_if {| key, value | block } -> hsh + * + * Deletes every key-value pair from <i>hsh</i> for which <i>block</i> + * evaluates to <code>false</code>. + * + */ + +VALUE +rb_hash_keep_if(VALUE hash) +{ + RETURN_ENUMERATOR(hash, 0, 0); + rb_hash_modify(hash); + rb_hash_foreach(hash, keep_if_i, hash); + return hash; +} + +static int clear_i(VALUE key, VALUE value, VALUE dummy) { return ST_DELETE; @@ -2367,6 +2418,37 @@ return result; } +static VALUE +env_select_bang(VALUE ehash) +{ + volatile VALUE keys; + long i; + int del = 0; + + RETURN_ENUMERATOR(ehash, 0, 0); + keys = env_keys(); /* rb_secure(4); */ + for (i=0; i<RARRAY_LEN(keys); i++) { + VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]); + if (!NIL_P(val)) { + if (!RTEST(rb_yield_values(2, RARRAY_PTR(keys)[i], val))) { + FL_UNSET(RARRAY_PTR(keys)[i], FL_TAINT); + env_delete(Qnil, RARRAY_PTR(keys)[i]); + del++; + } + } + } + if (del == 0) return Qnil; + return envtbl; +} + +static VALUE +env_keep_if(VALUE ehash) +{ + RETURN_ENUMERATOR(ehash, 0, 0); + env_select_bang(ehash); + return envtbl; +} + VALUE rb_env_clear(void) { @@ -2755,7 +2837,9 @@ rb_define_method(rb_cHash,"shift", rb_hash_shift, 0); rb_define_method(rb_cHash,"delete", rb_hash_delete, 1); rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0); + rb_define_method(rb_cHash,"keep_if", rb_hash_keep_if, 0); rb_define_method(rb_cHash,"select", rb_hash_select, 0); + rb_define_method(rb_cHash,"select!", rb_hash_select_bang, 0); rb_define_method(rb_cHash,"reject", rb_hash_reject, 0); rb_define_method(rb_cHash,"reject!", rb_hash_reject_bang, 0); rb_define_method(rb_cHash,"clear", rb_hash_clear, 0); @@ -2792,10 +2876,12 @@ rb_define_singleton_method(envtbl,"each_value", env_each_value, 0); rb_define_singleton_method(envtbl,"delete", env_delete_m, 1); rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0); + rb_define_singleton_method(envtbl,"keep_if", env_keep_if, 0); rb_define_singleton_method(envtbl,"clear", rb_env_clear, 0); rb_define_singleton_method(envtbl,"reject", env_reject, 0); rb_define_singleton_method(envtbl,"reject!", env_reject_bang, 0); rb_define_singleton_method(envtbl,"select", env_select, 0); + rb_define_singleton_method(envtbl,"select!", env_select_bang, 0); rb_define_singleton_method(envtbl,"shift", env_shift, 0); rb_define_singleton_method(envtbl,"invert", env_invert, 0); rb_define_singleton_method(envtbl,"replace", env_replace, 1); Index: test/ruby/test_hash.rb =================================================================== --- test/ruby/test_hash.rb (revision 26802) +++ test/ruby/test_hash.rb (revision 26803) @@ -290,6 +290,13 @@ assert_equal(base.size, n) end + def test_delete_if + h = {1=>2,3=>4,5=>6} + assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 }) + h = {1=>2,3=>4,5=>6} + assert_equal({1=>2,3=>4,5=>6}, h.keep_if{true}) + end + def test_dup for taint in [ false, true ] for untrust in [ false, true ] @@ -736,6 +743,14 @@ assert_equal({3=>4,5=>6}, {1=>2,3=>4,5=>6}.select {|k, v| k + v >= 7 }) end + def test_select! + h = {1=>2,3=>4,5=>6} + assert_equal(h, h.select! {|k, v| k + v >= 7 }) + assert_equal({3=>4,5=>6}, h) + h = {1=>2,3=>4,5=>6} + assert_equal(nil, h.select!{true}) + end + def test_clear2 assert_equal({}, {1=>2,3=>4,5=>6}.clear) h = {1=>2,3=>4,5=>6} -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/