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

ruby-changes:54800

From: nobu <ko1@a...>
Date: Thu, 7 Feb 2019 17:14:15 +0900 (JST)
Subject: [ruby-changes:54800] nobu:r67020 (trunk): enum.c: Enumerable#tally

nobu	2019-02-07 17:14:10 +0900 (Thu, 07 Feb 2019)

  New Revision: 67020

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=67020

  Log:
    enum.c: Enumerable#tally
    
    * enum.c (enum_tally): new methods Enumerable#tally, which group
      and count elements of the collection.  [Feature #11076]

  Modified files:
    trunk/NEWS
    trunk/enum.c
    trunk/test/ruby/test_enum.rb
Index: enum.c
===================================================================
--- enum.c	(revision 67019)
+++ enum.c	(revision 67020)
@@ -935,6 +935,48 @@ enum_group_by(VALUE obj) https://github.com/ruby/ruby/blob/trunk/enum.c#L935
     return enum_hashify(obj, 0, 0, group_by_i);
 }
 
+static void
+tally_up(VALUE hash, VALUE group)
+{
+    VALUE tally = rb_hash_aref(hash, group);
+    if (NIL_P(tally)) {
+	tally = INT2FIX(1);
+    }
+    else if (FIXNUM_P(tally) && tally < INT2FIX(FIXNUM_MAX)) {
+	tally += INT2FIX(1) & ~FIXNUM_FLAG;
+    }
+    else {
+	tally = rb_big_plus(tally, INT2FIX(1));
+    }
+    rb_hash_aset(hash, group, tally);
+}
+
+static VALUE
+tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
+{
+    ENUM_WANT_SVALUE();
+    tally_up(hash, i);
+    return Qnil;
+}
+
+/*
+ *  call-seq:
+ *     enum.tally -> a_hash
+ *
+ *  Tallys the collection.  Returns a hash where the keys are the
+ *  elements and the values are numbers of elements in the collection
+ *  that correspond to the key.
+ *
+ *     (1..6).tally { |i| i%3 }   #=> {0=>2, 1=>2, 2=>2}
+ *
+ */
+
+static VALUE
+enum_tally(VALUE obj)
+{
+    return enum_hashify(obj, 0, 0, tally_i);
+}
+
 static VALUE
 first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
 {
@@ -4070,6 +4112,7 @@ Init_Enumerable(void) https://github.com/ruby/ruby/blob/trunk/enum.c#L4112
     rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
     rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
     rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
+    rb_define_method(rb_mEnumerable, "tally", enum_tally, 0);
     rb_define_method(rb_mEnumerable, "first", enum_first, -1);
     rb_define_method(rb_mEnumerable, "all?", enum_all, -1);
     rb_define_method(rb_mEnumerable, "any?", enum_any, -1);
Index: NEWS
===================================================================
--- NEWS	(revision 67019)
+++ NEWS	(revision 67020)
@@ -24,6 +24,12 @@ sufficient information, see the ChangeLo https://github.com/ruby/ruby/blob/trunk/NEWS#L24
 
 === Core classes updates (outstanding ones only)
 
+Enumerable::
+
+  New method::
+
+   * Added Enumerable#tally.  [Feature #11076]
+
 === Stdlib updates (outstanding ones only)
 
 CSV::
Index: test/ruby/test_enum.rb
===================================================================
--- test/ruby/test_enum.rb	(revision 67019)
+++ test/ruby/test_enum.rb	(revision 67020)
@@ -294,6 +294,11 @@ class TestEnumerable < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_enum.rb#L294
     assert_equal(h, @obj.each_with_index.group_by(&cond))
   end
 
+  def test_tally
+    h = {1 => 2, 2 => 2, 3 => 1}
+    assert_equal(h, @obj.tally)
+  end
+
   def test_first
     assert_equal(1, @obj.first)
     assert_equal([1, 2, 3], @obj.first(3))

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

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