diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | enum.c | 35 | ||||
-rw-r--r-- | test/ruby/test_enum.rb | 15 |
3 files changed, 55 insertions, 0 deletions
@@ -1,3 +1,8 @@ +Wed Jul 20 17:39:11 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * enum.c (enum_uniq): new method Enumerable#uniq. + [Feature #11090] + Wed Jul 20 17:35:23 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> * hash.c (rb_hash_add_new_element): add new element or do nothing @@ -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 <code>Enumerable</code> 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 |