[Feature:1.9] {Array,Enumerable}#uniq_by, #uniq_by!

e$B$J$+$@$G$9!#e(B

e$B%V%m%C%/$NCM$K$7$?$,$C$F0l0U$N$b$N$rA*$V!"e(BArray#uniq_bye$B$H$$$&$Ne(B
e$B$O$I$&$G$7$g$&$+!#e(B

Index: array.c

— array.c (revision 22100)
+++ array.c (working copy)
@@ -2875,13 +2875,40 @@ ary_add_hash(VALUE hash, VALUE ary)
}

-static VALUE
-ary_make_hash(VALUE ary)
+static inline VALUE
+ary_tmp_hash_new(void)
{
VALUE hash = rb_hash_new();

 RBASIC(hash)->klass = 0;
  • return hash;
    +}

+static VALUE
+ary_make_hash(VALUE ary)
+{

  • VALUE hash = ary_tmp_hash_new();
    return ary_add_hash(hash, ary);
    }

+static VALUE
+ary_add_hash_by(VALUE hash, VALUE ary)
+{

  • long i;
  • for (i = 0; i < RARRAY_LEN(ary); ++i) {
  • VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
  • if (rb_hash_lookup2(hash, k, Qundef) == Qundef) {
  •  rb_hash_aset(hash, k, v);
    
  • }
  • }
  • return hash;
    +}

+static VALUE
+ary_make_hash_by(VALUE ary)
+{

  • VALUE hash = ary_tmp_hash_new();
  • return ary_add_hash_by(hash, ary);
    +}

static inline void
ary_recycle_hash(VALUE hash)
@@ -3063,4 +3090,43 @@ rb_ary_uniq(VALUE ary)
}

+static int
+push_value(st_data_t key, st_data_t val, st_data_t ary)
+{

  • rb_ary_push((VALUE)ary, (VALUE)val);
  • return ST_DELETE;
    +}

+static VALUE
+rb_ary_uniq_by_bang(VALUE ary)
+{

  • VALUE hash;
  • long size;
  • RETURN_ENUMERATOR(ary, 0, 0);
  • hash = ary_make_hash_by(ary);
  • size = RHASH_SIZE(hash);
  • if (RARRAY_LEN(ary) == size) return Qnil;
  • ary_resize_capa(ary, size);
  • ARY_SET_LEN(ary, 0);
  • st_foreach(RHASH_TBL(hash), push_value, ary);
  • ary_recycle_hash(hash);
  • return ary;
    +}

+static VALUE
+rb_ary_uniq_by(VALUE ary)
+{

  • VALUE hash;
  • long size;
  • RETURN_ENUMERATOR(ary, 0, 0);
  • hash = ary_make_hash_by(ary);
  • size = RHASH_SIZE(hash);
  • ary = ary_new(rb_obj_class(ary), size);
  • st_foreach(RHASH_TBL(hash), push_value, ary);
  • ary_recycle_hash(hash);
  • return ary;
    +}

/*

  • call-seq:
    @@ -3920,4 +3986,6 @@ Init_Array(void)
    rb_define_method(rb_cArray, “uniq”, rb_ary_uniq, 0);
    rb_define_method(rb_cArray, “uniq!”, rb_ary_uniq_bang, 0);
  • rb_define_method(rb_cArray, “uniq_by”, rb_ary_uniq_by, 0);
  • rb_define_method(rb_cArray, “uniq_by!”, rb_ary_uniq_by_bang, 0);
    rb_define_method(rb_cArray, “compact”, rb_ary_compact, 0);
    rb_define_method(rb_cArray, “compact!”, rb_ary_compact_bang, 0);
    Index: enum.c
    ===================================================================
    — enum.c (revision 22100)
    +++ enum.c (working copy)
    @@ -1794,4 +1794,29 @@ enum_cycle(int argc, VALUE *argv, VALUE
    }

+static VALUE
+enum_uniq_by_i(VALUE i, VALUE hash, int argc, VALUE *argv)
+{

  • return rb_hash_aset(hash, rb_yield_values(argc, argv), i);
    +}

+static int
+push_value(st_data_t key, st_data_t val, st_data_t ary)
+{

  • rb_ary_push((VALUE)ary, (VALUE)val);
  • return ST_DELETE;
    +}

+static VALUE
+enum_uniq_by(VALUE obj)
+{

  • VALUE hash = rb_hash_new(), uniq;
  • RBASIC(hash)->klass = 0;
  • rb_block_call(obj, id_each, 0, 0, enum_uniq_by_i, hash);
  • uniq = rb_ary_new2(RHASH_SIZE(hash));
  • st_foreach(RHASH_TBL(hash), push_value, uniq);
  • return uniq;
    +}

/*

  • The Enumerable mixin provides collection classes with
    @@ -1853,4 +1878,5 @@ Init_Enumerable(void)
    rb_define_method(rb_mEnumerable, “drop_while”, enum_drop_while, 0);
    rb_define_method(rb_mEnumerable, “cycle”, enum_cycle, -1);
  • rb_define_method(rb_mEnumerable, “uniq_by”, enum_uniq_by, 0);

    id_eqq = rb_intern("===");

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:37998] [Feature:1.9]
{Array,Enumerable}#uniq_by, #uniq_by!”
on Fri, 13 Feb 2009 22:19:41 +0900, Nobuyoshi N.
[email protected] writes:

|e$B%V%m%C%/$NCM$K$7$?$,$C$F0l0U$N$b$N$rA*$V!"e(BArray#uniq_bye$B$H$$$&$Ne(B
|e$B$O$I$&$G$7$g$&$+!#e(B

e$B8=:_%V%m%C%/$r<u$1IU$1$F$$$J$$$N$G$9$+$i!“e(Buniq_bye$B$r?75,$KF3F~e(B
e$B$9$k$h$j$be(B uniq{|x| f(x}
e$B$G!V%V%m%C%/$NCM$K=>$C$F0l0U$N$b$N$re(B
e$BA*$V!WJ}$,NI$$$N$G$O$J$$$G$7$g$&$+!#e(Bsort, maxe$B$H$O0[$J$j$^$9e(B
e$B$,!”$3$l$i$O85$+$i%V%m%C%/$r<h$C$F$$$^$7$?$+$i!#e(B

e$B%A%1%C%He(B #1154 e$B$,99?7$5$l$^$7$?!#e(B (by Nobuyoshi N.)

e$B%9%F!<%?%9e(B Opene$B$+$ie(BClosede$B$KJQ99e(B
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

Applied in changeset r22307.

http://redmine.ruby-lang.org/issues/show/1154

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:38015] Re: [Feature:1.9]
{Array,Enumerable}#uniq_by, #uniq_by!”
on Sun, 15 Feb 2009 06:59:09 +0900, Kazuhiro NISHIYAMA
[email protected] writes:

|uniq_bye$B$NJ}$,%V%m%C%/$J$7$N;~$Ke(BEnumeratore$B$,F@$i$l$FJXMx$+$be(B
|e$B$7$l$J$$$H;W$C$?$N$G$9$,!"$I$&$G$7$g$&$+e(B?

e$B%V%m%C%/$J$7$Ge(BEnumeratore$B$r$b$i$C$F$&$l$7$$>l9g$,;W$$$D$-$^$;e(B
e$B$s!#$`$7$m!"%V%m%C%/$rEO$7$Fe(B(e$BG[Ns$G$O$J$/e(B)Enumeratore$B$G$[$7$$e(B
e$B$H$$$&$J$i$o$+$j$^$9$,!#e(B

e$B@>;3OB9-$G$9!#e(B

At Sat, 14 Feb 2009 18:19:59 +0900,
Yukihiro M. wrote:

|e$B%V%m%C%/$NCM$K$7$?$,$C$F0l0U$N$b$N$rA*$V!"e(BArray#uniq_bye$B$H$$$&$Ne(B
|e$B$O$I$&$G$7$g$&$+!#e(B

e$B8=:_%V%m%C%/$r<u$1IU$1$F$$$J$$$N$G$9$+$i!“e(Buniq_bye$B$r?75,$KF3F~e(B
e$B$9$k$h$j$be(B uniq{|x| f(x} e$B$G!V%V%m%C%/$NCM$K=>$C$F0l0U$N$b$N$re(B
e$BA*$V!WJ}$,NI$$$N$G$O$J$$$G$7$g$&$+!#e(Bsort, maxe$B$H$O0[$J$j$^$9e(B
e$B$,!”$3$l$i$O85$+$i%V%m%C%/$r<h$C$F$$$^$7$?$+$i!#e(B

uniq_bye$B$NJ}$,%V%m%C%/$J$7$N;~$Ke(BEnumeratore$B$,F@$i$l$FJXMx$+$be(B
e$B$7$l$J$$$H;W$C$?$N$G$9$,!"$I$&$G$7$g$&$+e(B?