[前][次][番号順一覧][スレッド一覧]

ruby-changes:14929

From: matz <ko1@a...>
Date: Wed, 3 Mar 2010 14:36:19 +0900 (JST)
Subject: [ruby-changes:14929] Ruby:r26800 (trunk): * array.c (rb_ary_select_bang): select! removes all elements for

matz	2010-03-03 14:35:08 +0900 (Wed, 03 Mar 2010)

  New Revision: 26800

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=26800

  Log:
    * array.c (rb_ary_select_bang): select! removes all elements for
      which block returns false.  [ruby-core:27286]
    
    * array.c (rb_ary_keep_if): #keep_if, new method.

  Modified files:
    trunk/ChangeLog
    trunk/array.c
    trunk/test/ruby/test_array.rb

Index: array.c
===================================================================
--- array.c	(revision 26799)
+++ array.c	(revision 26800)
@@ -2250,6 +2250,57 @@
 
 /*
  *  call-seq:
+ *     array.select! {|item| block } -> an_array
+ *
+ *  Invokes the block passing in successive elements from
+ *  <i>array</i>, deleting elements for which the block returns a
+ *  false value.  but returns <code>nil</code> if no changes were
+ *  made.  Also see <code>Array#keep_if</code>
+ */
+
+static VALUE
+rb_ary_select_bang(VALUE ary)
+{
+    long i1, i2;
+
+    RETURN_ENUMERATOR(ary, 0, 0);
+    rb_ary_modify(ary);
+    for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
+	VALUE v = RARRAY_PTR(ary)[i1];
+	if (!RTEST(rb_yield(v))) continue;
+	if (i1 != i2) {
+	    rb_ary_store(ary, i2, v);
+	}
+	i2++;
+    }
+
+    if (RARRAY_LEN(ary) == i2) return Qnil;
+    if (i2 < RARRAY_LEN(ary))
+	ARY_SET_LEN(ary, i2);
+    return ary;
+}
+
+/*
+ *  call-seq:
+ *     array.keep_if {|item| block } -> an_array
+ *
+ *  Deletes every element of <i>self</i> for which <i>block</i> evaluates
+ *  to <code>false</code>.
+ *
+ *     a = %w{ a b c d e f }
+ *     a.keep_if {|v| v =~ /[aeiou]/}   #=> ["a", "e"]
+ */
+
+static VALUE
+rb_ary_keep_if(VALUE ary)
+{
+    RETURN_ENUMERATOR(ary, 0, 0);
+    rb_ary_select_bang(ary);
+    return ary;
+}
+
+/*
+ *  call-seq:
  *     array.delete(obj)            -> obj or nil
  *     array.delete(obj) { block }  -> obj or nil
  *
@@ -4239,6 +4290,8 @@
     rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
     rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
     rb_define_method(rb_cArray, "select", rb_ary_select, 0);
+    rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
+    rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
     rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
     rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
     rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 26799)
+++ ChangeLog	(revision 26800)
@@ -1,3 +1,10 @@
+Wed Mar  3 14:28:23 2010  Yukihiro Matsumoto  <matz@r...>
+
+	* array.c (rb_ary_select_bang): select! removes all elements for
+	  which block returns false.  [ruby-core:27286]
+
+	* array.c (rb_ary_keep_if): #keep_if, new method.
+
 Wed Mar  3 06:19:25 2010  Nobuyoshi Nakada  <nobu@r...>
 
 	* win32/win32.c (signbig): defined.
Index: test/ruby/test_array.rb
===================================================================
--- test/ruby/test_array.rb	(revision 26799)
+++ test/ruby/test_array.rb	(revision 26800)
@@ -1590,6 +1590,22 @@
     assert_equal([0, 2], [0, 1, 2, 3].select {|x| x % 2 == 0 })
   end
 
+  # also keep_if
+  def test_select!
+    a = @cls[ 1, 2, 3, 4, 5 ]
+    assert_equal(nil, a.select! { true })
+    assert_equal(a, a.keep_if { true })
+    assert_equal(@cls[1, 2, 3, 4, 5], a)
+
+    a = @cls[ 1, 2, 3, 4, 5 ]
+    assert_equal(a, a.select! { false })
+    assert_equal(@cls[], a)
+
+    a = @cls[ 1, 2, 3, 4, 5 ]
+    assert_equal(a, a.select! { |i| i > 3 })
+    assert_equal(@cls[4, 5], a)
+  end
+
   def test_delete2
     a = [0] * 1024 + [1] + [0] * 1024
     a.delete(0)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]