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/