From 42c6a5137e46b885ab28b267f85c0ddc8d49b195 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 20 Jul 2016 08:39:12 +0000 Subject: enum.c: Enumerable#uniq * enum.c (enum_uniq): new method Enumerable#uniq. [Feature #11090] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55709 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ enum.c | 35 +++++++++++++++++++++++++++++++++++ test/ruby/test_enum.rb | 15 +++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/ChangeLog b/ChangeLog index f6834c8f13..1baba4f7d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed Jul 20 17:39:11 2016 Nobuyoshi Nakada + + * enum.c (enum_uniq): new method Enumerable#uniq. + [Feature #11090] + Wed Jul 20 17:35:23 2016 Nobuyoshi Nakada * hash.c (rb_hash_add_new_element): add new element or do nothing diff --git a/enum.c b/enum.c index b62f7c3f37..fb1150a8a4 100644 --- a/enum.c +++ b/enum.c @@ -3793,6 +3793,40 @@ enum_sum(int argc, VALUE* argv, VALUE obj) } } +static VALUE +uniq_func(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) +{ + rb_hash_add_new_element(hash, i, i); + return Qnil; +} + +static VALUE +uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) +{ + rb_hash_add_new_element(hash, rb_yield_values2(argc, argv), i); + return Qnil; +} + +/* + * call-seq: + * enum.uniq -> new_ary + * enum.uniq { |item| ... } -> new_ary + */ + +static VALUE +enum_uniq(VALUE obj) +{ + VALUE hash, ret; + rb_block_call_func *const func = + rb_block_given_p() ? uniq_iter : uniq_func; + + hash = rb_obj_hide(rb_hash_new()); + rb_block_call(obj, id_each, 0, 0, func, hash); + ret = rb_hash_values(hash); + rb_hash_clear(hash); + return ret; +} + /* * The Enumerable mixin provides collection classes with * several traversal and searching methods, and with the ability to @@ -3866,6 +3900,7 @@ Init_Enumerable(void) rb_define_method(rb_mEnumerable, "slice_when", enum_slice_when, 0); rb_define_method(rb_mEnumerable, "chunk_while", enum_chunk_while, 0); rb_define_method(rb_mEnumerable, "sum", enum_sum, -1); + rb_define_method(rb_mEnumerable, "uniq", enum_uniq, 0); id_next = rb_intern("next"); id_call = rb_intern("call"); diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb index df75a80c50..d2403dd1a1 100644 --- a/test/ruby/test_enum.rb +++ b/test/ruby/test_enum.rb @@ -921,4 +921,19 @@ class TestEnumerable < Test::Unit::TestCase assert_int_equal(2, (2..2).sum) assert_int_equal(42, (2...2).sum(42)) end + + def test_uniq + src = [1, 1, 1, 1, 2, 2, 3, 4, 5, 6] + assert_equal([1, 2, 3, 4, 5, 6], src.uniq.to_a) + olimpics = { + 1896 => 'Athens', + 1900 => 'Paris', + 1904 => 'Chikago', + 1906 => 'Athens', + 1908 => 'Rome', + } + assert_equal([[1896, "Athens"], [1900, "Paris"], [1904, "Chikago"], [1908, "Rome"]], + olimpics.uniq{|k,v| v}) + assert_equal([1, 2, 3, 4, 5, 10], (1..100).uniq{|x| (x**2) % 10 }.first(6)) + end end -- cgit v1.2.3