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

ruby-changes:4511

From: ko1@a...
Date: Mon, 14 Apr 2008 16:04:51 +0900 (JST)
Subject: [ruby-changes:4511] knu - Ruby:r16004 (ruby_1_8): * enum.c (enum_count, enum_find_index): New methods:

knu	2008-04-14 16:04:30 +0900 (Mon, 14 Apr 2008)

  New Revision: 16004

  Modified files:
    branches/ruby_1_8/ChangeLog
    branches/ruby_1_8/NEWS
    branches/ruby_1_8/array.c
    branches/ruby_1_8/enum.c

  Log:
    * enum.c (enum_count, enum_find_index): New methods:
      Enumerable#count and #find_index; backported from 1.9.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/enum.c?r1=16004&r2=16003&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/ChangeLog?r1=16004&r2=16003&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/array.c?r1=16004&r2=16003&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/NEWS?r1=16004&r2=16003&diff_format=u

Index: ruby_1_8/array.c
===================================================================
--- ruby_1_8/array.c	(revision 16003)
+++ ruby_1_8/array.c	(revision 16004)
@@ -945,6 +945,8 @@
  *     a.index("b")        #=> 1
  *     a.index("z")        #=> nil
  *     a.index{|x|x=="b"}  #=> 1
+ *
+ *  This is an alias of <code>#find_index</code>.
  */
 
 static VALUE
@@ -3157,6 +3159,7 @@
     rb_define_method(rb_cArray, "length", rb_ary_length, 0);
     rb_define_alias(rb_cArray,  "size", "length");
     rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
+    rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
     rb_define_method(rb_cArray, "index", rb_ary_index, -1);
     rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
     rb_define_method(rb_cArray, "indexes", rb_ary_indexes, -1);
Index: ruby_1_8/NEWS
===================================================================
--- ruby_1_8/NEWS	(revision 16003)
+++ ruby_1_8/NEWS	(revision 16004)
@@ -54,6 +54,8 @@
 
     New methods for various enumeration defined by the enumerator library.
 
+  * Enumerator#count
+  * Enumerable#find_index
   * Enumerable#first
   * Enumerable#group_by
 
Index: ruby_1_8/ChangeLog
===================================================================
--- ruby_1_8/ChangeLog	(revision 16003)
+++ ruby_1_8/ChangeLog	(revision 16004)
@@ -1,3 +1,8 @@
+Mon Apr 14 15:49:05 2008  Akinori MUSHA  <knu@i...>
+
+	* enum.c (enum_count, enum_find_index): New methods:
+	  Enumerable#count and #find_index; backported from 1.9.
+
 Mon Apr 14 14:16:08 2008  NAKAMURA Usaku  <usa@r...>
 
 	* enumerator.c (enumerator_mark, enumerator_iter_i, enumerator_each_i,
Index: ruby_1_8/enum.c
===================================================================
--- ruby_1_8/enum.c	(revision 16003)
+++ ruby_1_8/enum.c	(revision 16004)
@@ -114,6 +114,75 @@
 }
 
 static VALUE
+count_i(i, arg)
+     VALUE i;
+     VALUE *arg;
+{
+    if (rb_equal(i, arg[0])) {
+	arg[1]++;
+    }
+    return Qnil;
+}
+
+static VALUE
+count_iter_i(i, n)
+     VALUE i;
+     long *n;
+{
+    if (RTEST(rb_yield(i))) {
+	(*n)++;
+    }
+    return Qnil;
+}
+
+/*
+ *  call-seq:
+ *     enum.count(item)             => int
+ *     enum.count {| obj | block }  => int
+ *  
+ *  Returns the number of items in <i>enum</i> for which equals to <i>item</i>.
+ *  If a block is given, counts the number of elements yielding a true value.
+ *     
+ *     ary = [1, 2, 4, 2]
+ *     ary.count(2)          # => 2
+ *     ary.count{|x|x%2==0}  # => 3
+ *     
+ */
+
+static VALUE
+enum_count(argc, argv, obj)
+    int argc;
+    VALUE *argv;
+    VALUE obj;
+{
+    if (argc == 1) {
+	VALUE item, args[2];
+
+	if (rb_block_given_p()) {
+	    rb_warn("given block not used");
+	}
+	rb_scan_args(argc, argv, "1", &item);
+	args[0] = item;
+	args[1] = 0;
+	rb_block_call(obj, id_each, 0, 0, count_i, (VALUE)&args);
+	return INT2NUM(args[1]);
+    }
+    else if (argc == 0) {
+	long n;
+
+	RETURN_ENUMERATOR(obj, 0, 0);
+	n = 0;
+	rb_block_call(obj, id_each, 0, 0, count_iter_i, (VALUE)&n);
+	return INT2NUM(n);
+    }
+    else {
+        VALUE v;
+	rb_scan_args(argc, argv, "1", &v);
+        return Qnil; /* not reached */
+    }
+}
+
+static VALUE
 find_i(i, memo)
     VALUE i;
     VALUE *memo;
@@ -161,6 +230,79 @@
 }
 
 static VALUE
+find_index_i(i, memop)
+    VALUE i;
+    VALUE memop;
+{
+    VALUE *memo = (VALUE*)memop;
+
+    if (rb_equal(i, memo[2])) {
+	memo[0] = UINT2NUM(memo[1]);
+	rb_iter_break();
+    }
+    memo[1]++;
+    return Qnil;
+}
+
+static VALUE
+find_index_iter_i(i, memop)
+    VALUE i;
+    VALUE memop;
+{
+    VALUE *memo = (VALUE*)memop;
+
+    if (RTEST(rb_yield(i))) {
+	memo[0] = UINT2NUM(memo[1]);
+	rb_iter_break();
+    }
+    memo[1]++;
+    return Qnil;
+}
+
+/*
+ *  call-seq:
+ *     enum.find_index(value)            => int or nil
+ *     enum.find_index {| obj | block }  => int or nil
+ *  
+ *  Compares each entry in <i>enum</i> with <em>value</em> or passes
+ *  to <em>block</em>.  Returns the index for the first for which the
+ *  evaluated value is non-false.  If no object matches, returns
+ *  <code>nil</code>
+ *     
+ *     (1..10).find_index  {|i| i % 5 == 0 and i % 7 == 0 }   #=> nil
+ *     (1..100).find_index {|i| i % 5 == 0 and i % 7 == 0 }   #=> 34
+ *     (1..100).find_index(50)                                #=> 49
+ *     
+ */
+
+static VALUE
+enum_find_index(argc, argc, obj)
+    int argc;
+    VALUE *argv;
+    VALUE obj;
+{
+    VALUE memo[3];	/* [return value, current index, condition value] */
+    rb_block_call_func *func;
+
+    if (argc == 0) {
+        RETURN_ENUMERATOR(obj, 0, 0);
+        func = find_index_iter_i;
+    }
+    else {
+	rb_scan_args(argc, argv, "1", &memo[2]);
+	if (rb_block_given_p()) {
+	    rb_warn("given block not used");
+	}
+        func = find_index_i;
+    }
+
+    memo[0] = Qnil;
+    memo[1] = 0;
+    rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
+    return memo[0];
+}
+
+static VALUE
 find_all_i(i, ary)
     VALUE i, ary;
 {
@@ -1050,8 +1192,10 @@
     rb_define_method(rb_mEnumerable,"sort", enum_sort, 0);
     rb_define_method(rb_mEnumerable,"sort_by", enum_sort_by, 0);
     rb_define_method(rb_mEnumerable,"grep", enum_grep, 1);
+    rb_define_method(rb_mEnumerable,"count", enum_count, -1);
     rb_define_method(rb_mEnumerable,"find", enum_find, -1);
     rb_define_method(rb_mEnumerable,"detect", enum_find, -1);
+    rb_define_method(rb_mEnumerable,"find_index", enum_find_index, 0);
     rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0);
     rb_define_method(rb_mEnumerable,"select", enum_find_all, 0);
     rb_define_method(rb_mEnumerable,"reject", enum_reject, 0);

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

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