最近 Ruby の中身に関わる時間が取れないのですが、書いている
プログラムで欲しくなったメソッドがあるので、実装してみました。

Array#merge(obj1[, obj2, ...])

	与えられたオブジェクトのうち、配列に含まれない要素を
	追加する。重複する要素は一つだけになる。

	a.merge(*x) と a.replace(a | x) はほぼ等価である。
	(|= を破壊的に行う)

Array#squeeze([obj, ...])
Array#squeeze!([obj, ...])

	同じ要素の連続を一つに圧縮する。引数が指定された場合は
	引数に含まれるもののみを対象に圧縮する。

	String#squeeze の配列版。


実装において、 ary_make_hash() の argc, argv 対応版が必要だった
ので ary_make_hash2() として用意し、 ary_make_hash() の下請けと
しました。


 ほかにもいいと思う人が多ければ 1.7 に入れたいなあと思いますが、
いかがでしょうか?名前や実装についても突っ込みがあればよろしく。


# union(!), unify(!) なども考えたが、ある程度対等な関係であれば
# | を使う方が見た目もよいので、ニュアンスからも merge が適当と
# 判断した。

-- 
                     /
                    /__  __            Akinori.org / MUSHA.org
                   / )  )  ) )  /     FreeBSD.org / Ruby-lang.org
Akinori MUSHA aka / (_ /  ( (__(  @ iDaemons.org / and.or.jp

"Freeze this moment a little bit longer, make each impression
  a little bit stronger..  Experience slips away -- Time stand still"

Index: array.c
===================================================================
RCS file: /src/ruby/array.c,v
retrieving revision 1.56
diff -u -r1.56 array.c
--- array.c	2001/08/23 06:02:14	1.56
+++ array.c	2001/08/27 08:40:12
@@ -1485,24 +1485,36 @@
 }
 
 static VALUE
-ary_make_hash(ary1, ary2)
-    VALUE ary1, ary2;
+ary_make_hash2(ary, argc2, argv2)
+    VALUE ary;
+    int argc2;
+    VALUE *argv2;
 {
     VALUE hash = rb_hash_new();
+    int argc1 = RARRAY(ary)->len;
+    VALUE *argv1 = RARRAY(ary)->ptr;
     int i;
 
-    for (i=0; i<RARRAY(ary1)->len; i++) {
-	rb_hash_aset(hash, RARRAY(ary1)->ptr[i], Qtrue);
+    for (i = 0; i < argc1; i++) {
+	rb_hash_aset(hash, argv1[i], Qtrue);
     }
-    if (ary2) {
-	for (i=0; i<RARRAY(ary2)->len; i++) {
-	    rb_hash_aset(hash, RARRAY(ary2)->ptr[i], Qtrue);
-	}
+    for (i = 0; i < argc2; i++) {
+	rb_hash_aset(hash, argv2[i], Qtrue);
     }
     return hash;
 }
 
 static VALUE
+ary_make_hash(ary1, ary2)
+    VALUE ary1, ary2;
+{
+    if (ary2)
+	return ary_make_hash2(ary1, RARRAY(ary2)->len, RARRAY(ary2)->ptr);
+    else
+	return ary_make_hash2(ary1, 0, 0);
+}
+
+static VALUE
 rb_ary_and(ary1, ary2)
     VALUE ary1, ary2;
 {
@@ -1552,6 +1564,44 @@
 }
 
 static VALUE
+rb_ary_merge(argc, argv, ary)
+    int argc;
+    VALUE *argv;
+    VALUE ary;
+{
+    VALUE hash = ary_make_hash2(ary, argc, argv);
+    VALUE *p;
+    long i, j, len;
+
+    rb_ary_modify(ary);
+
+    p = RARRAY(ary)->ptr;
+    len = RARRAY(ary)->len;
+
+    for (i = j = 0; j < len; j++) {
+	VALUE v = p[j];
+	if (st_delete(RHASH(hash)->tbl, &v, 0)) {
+	    p[i++] = p[j];
+	}
+    }
+
+    RARRAY(ary)->len = RARRAY(ary)->capa =
+      len = i + RHASH(hash)->tbl->num_entries;
+    REALLOC_N(RARRAY(ary)->ptr, VALUE, len);
+
+    p = RARRAY(ary)->ptr;
+
+    for (j = 0; j < argc; j++) {
+	VALUE v = argv[j];
+	if (st_delete(RHASH(hash)->tbl, &v, 0)) {
+	    p[i++] = argv[j];
+	}
+    }
+
+    return ary;
+}
+
+static VALUE
 rb_ary_uniq_bang(ary)
     VALUE ary;
 {
@@ -1618,6 +1668,73 @@
 }
 
 static VALUE
+rb_ary_squeeze_bang(argc, argv, ary)
+    int argc;
+    VALUE *argv;
+    VALUE ary;
+{
+    int included;
+    long i, j, k, len;
+    VALUE *ptr, prev;
+
+    len = RARRAY(ary)->len;
+
+    if (len <= 1) return ary;
+
+    rb_ary_modify(ary);
+    ptr = RARRAY(ary)->ptr;
+
+    for (i = j = 0; ;) {
+	prev = ptr[j];
+
+	i++, j++;
+
+	if (len <= j) goto done;
+
+	if (argc > 0) {
+	    included = 0;
+
+	    for (k = 0; k < argc; k++) {
+		if (rb_equal(argv[k], ptr[j])) {
+		    included = 1;
+		    break;
+		}
+	    }
+	}
+	else {
+	    included = 1;
+	}
+
+	if (included) {
+	    while (rb_equal(prev, ptr[j])) {
+		j++;
+
+		if (len <= j) goto done;
+	    }
+	}
+
+	if (i != j) ptr[i] = ptr[j];
+    }
+
+  done:
+    RARRAY(ary)->len = RARRAY(ary)->capa = i;
+    REALLOC_N(RARRAY(ary)->ptr, VALUE, i);
+
+    return ary;
+}
+
+static VALUE
+rb_ary_squeeze(argc, argv, ary)
+    int argc;
+    VALUE *argv;
+    VALUE ary;
+{
+    ary = rb_ary_dup(ary);
+    rb_ary_squeeze_bang(argc, argv, ary);
+    return ary;
+}
+
+static VALUE
 rb_ary_nitems(ary)
     VALUE ary;
 {
@@ -1773,12 +1890,15 @@
     rb_define_method(rb_cArray, "&", rb_ary_and, 1);
     rb_define_method(rb_cArray, "|", rb_ary_or, 1);
 
+    rb_define_method(rb_cArray, "merge", rb_ary_merge, -1);
     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, "compact", rb_ary_compact, 0);
     rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
     rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
     rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, 0);
+    rb_define_method(rb_cArray, "squeeze", rb_ary_squeeze, -1);
+    rb_define_method(rb_cArray, "squeeze!", rb_ary_squeeze_bang, -1);
     rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0);
 
     cmp = rb_intern("<=>");