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

ruby-changes:31322

From: marcandre <ko1@a...>
Date: Thu, 24 Oct 2013 00:10:55 +0900 (JST)
Subject: [ruby-changes:31322] marcandRe: r43401 (trunk): * array.c: Add Array#to_h [Feature #7292]

marcandre	2013-10-24 00:10:48 +0900 (Thu, 24 Oct 2013)

  New Revision: 43401

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

  Log:
    * array.c: Add Array#to_h [Feature #7292]
    
    * enum.c: Add Enumerable#to_h

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/array.c
    trunk/enum.c
    trunk/test/ruby/test_array.rb
    trunk/test/ruby/test_enum.rb
Index: array.c
===================================================================
--- array.c	(revision 43400)
+++ array.c	(revision 43401)
@@ -2126,6 +2126,32 @@ rb_ary_to_a(VALUE ary) https://github.com/ruby/ruby/blob/trunk/array.c#L2126
 
 /*
  *  call-seq:
+ *     ary.to_h     -> hash
+ *
+ *  Returns the result of interpreting <i>ary</i> as an array of
+ *  <tt>[key, value]</tt> pairs. Elements other than pairs of
+ *  values are ignored.
+ *
+ *     [[:foo, :bar], [1, 2]].to_h
+ *       # => {:foo => :bar, 1 => 2}
+ */
+
+static VALUE
+rb_ary_to_h(VALUE ary)
+{
+    long i;
+    VALUE hash = rb_hash_new();
+    for (i=0; i<RARRAY_LEN(ary); i++) {
+	VALUE key_value_pair = rb_check_array_type(rb_ary_elt(ary, i));
+	if (!NIL_P(key_value_pair) && (RARRAY_LEN(key_value_pair) == 2)) {
+	    rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
+	}
+    }
+    return hash;
+}
+
+/*
+ *  call-seq:
  *     ary.to_ary -> ary
  *
  *  Returns +self+.
@@ -5564,6 +5590,7 @@ Init_Array(void) https://github.com/ruby/ruby/blob/trunk/array.c#L5590
     rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
     rb_define_alias(rb_cArray,  "to_s", "inspect");
     rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
+    rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
     rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
     rb_define_method(rb_cArray, "frozen?",  rb_ary_frozen_p, 0);
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 43400)
+++ ChangeLog	(revision 43401)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Oct 24 00:10:22 2013  Marc-Andre Lafortune  <ruby-core@m...>
+
+	* array.c: Add Array#to_h [Feature #7292]
+
+	* enum.c: Add Enumerable#to_h
+
 Wed Oct 23 23:48:28 2013  Aman Gupta <ruby@t...>
 
 	* gc.c: Rename free_min to min_free_slots and free_min_page to
Index: enum.c
===================================================================
--- enum.c	(revision 43400)
+++ enum.c	(revision 43401)
@@ -510,6 +510,39 @@ enum_to_a(int argc, VALUE *argv, VALUE o https://github.com/ruby/ruby/blob/trunk/enum.c#L510
 }
 
 static VALUE
+enum_to_h_i(VALUE i, VALUE hash, int argc, VALUE *argv)
+{
+    ENUM_WANT_SVALUE();
+    rb_thread_check_ints();
+    i = rb_check_array_type(i);
+    if (!NIL_P(i) && RARRAY_LEN(i) == 2) {
+	rb_hash_aset(hash, RARRAY_AREF(i, 0), RARRAY_AREF(i, 1));
+    }
+    return Qnil;
+}
+
+/*
+ *  call-seq:
+ *     enum.to_h(*args)  -> hash
+ *
+ *  Returns the result of interpreting <i>enum</i> as a list of
+ *  <tt>[key, value]</tt> pairs. Elements other than pairs of
+ *  values are ignored.
+ *
+ *     %i[hello world].each_with_index.to_h
+ *       # => {:hello => 0, :world => 1}
+ */
+
+static VALUE
+enum_to_h(int argc, VALUE *argv, VALUE obj)
+{
+    VALUE hash = rb_hash_new();
+    rb_block_call(obj, id_each, argc, argv, enum_to_h_i, hash);
+    OBJ_INFECT(hash, obj);
+    return hash;
+}
+
+static VALUE
 inject_i(VALUE i, VALUE p, int argc, VALUE *argv)
 {
     NODE *memo = RNODE(p);
@@ -2758,6 +2791,7 @@ Init_Enumerable(void) https://github.com/ruby/ruby/blob/trunk/enum.c#L2791
 
     rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
     rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
+    rb_define_method(rb_mEnumerable, "to_h", enum_to_h, -1);
 
     rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
     rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
Index: NEWS
===================================================================
--- NEWS	(revision 43400)
+++ NEWS	(revision 43401)
@@ -31,12 +31,20 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L31
 
 === Core classes updates (outstanding ones only)
 
+* Array
+  * New methods
+    * Array#to_h converts an array of key-value pairs into a Hash.
+
 * Binding
   * New methods
     * Binding#local_variable_get(symbol)
     * Binding#local_variable_set(symbol, obj)
     * Binding#local_variable_defined?(symbol)
 
+* Enumerable
+  * New methods
+    * Enumerable#to_h converts a list of key-value pairs into a Hash.
+
 * GC
   * added environment variable:
     * RUBY_HEAP_SLOTS_GROWTH_FACTOR: growth rate of the heap.
Index: test/ruby/test_array.rb
===================================================================
--- test/ruby/test_array.rb	(revision 43400)
+++ test/ruby/test_array.rb	(revision 43401)
@@ -1456,6 +1456,21 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L1456
     $, = nil
   end
 
+  def test_to_h
+    kvp = Object.new
+    def kvp.to_ary
+      [:obtained, :via_to_ary]
+    end
+    array = [
+      [:key, :value],
+      [:ignore_me],
+      [:ignore, :me, :too],
+      :ignore_me,
+      kvp,
+    ]
+    assert_equal({key: :value, obtained: :via_to_ary}, array.to_h)
+  end
+
   def test_uniq
     a = []
     b = a.uniq
Index: test/ruby/test_enum.rb
===================================================================
--- test/ruby/test_enum.rb	(revision 43400)
+++ test/ruby/test_enum.rb	(revision 43401)
@@ -103,6 +103,33 @@ class TestEnumerable < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_enum.rb#L103
     assert_equal([1, 2, 3, 1, 2], @obj.to_a)
   end
 
+  def test_to_h
+    assert_equal({}, @obj.to_h)
+    obj = Object.new
+    def obj.each(*args)
+      yield args
+      yield [:key, :value]
+      yield [:ignore_me]
+      yield [:ignore, :me, :too]
+      yield :other_key, :other_value
+      yield :ignore_me
+      yield :ignore, :me, :too
+      yield
+      kvp = Object.new
+      def kvp.to_ary
+        [:obtained, :via_to_ary]
+      end
+      yield kvp
+    end
+    obj.extend Enumerable
+    assert_equal({
+      :hello => :world,
+      :key => :value,
+      :other_key => :other_value,
+      :obtained => :via_to_ary,
+    }, obj.to_h(:hello, :world))
+  end
+
   def test_inject
     assert_equal(12, @obj.inject {|z, x| z * x })
     assert_equal(48, @obj.inject {|z, x| z * 2 + x })

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

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