[前][次][番号順一覧][スレッド一覧]

ruby-changes:65878

From: Travis <ko1@a...>
Date: Fri, 16 Apr 2021 16:06:56 +0900 (JST)
Subject: [ruby-changes:65878] 55d91a096a (master): Add Array#intersect?

https://git.ruby-lang.org/ruby.git/commit/?id=55d91a096a

From 55d91a096a840aaff1e08a4286c216da56b6e968 Mon Sep 17 00:00:00 2001
From: Travis Hunter <travis.hunter@b...>
Date: Wed, 3 Oct 2018 15:19:36 -0400
Subject: Add Array#intersect?

---
 array.c                 | 56 +++++++++++++++++++++++++++++++++++++++++++++++++
 test/ruby/test_array.rb | 13 ++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/array.c b/array.c
index be744e2..f97be64 100644
--- a/array.c
+++ b/array.c
@@ -5567,6 +5567,61 @@ rb_ary_union_multi(int argc, VALUE *argv, VALUE ary) https://github.com/ruby/ruby/blob/trunk/array.c#L5567
     return ary_union;
 }
 
+/*
+ *  call-seq:
+ *     ary.intersect?(other_ary)   -> true or false
+ *
+ *  Returns +true+ if the array and +other_ary+ have at least one element in
+ *  common, otherwise returns +false+.
+ *
+ *     a = [ 1, 2, 3 ]
+ *     b = [ 3, 4, 5 ]
+ *     c = [ 5, 6, 7 ]
+ *     a.intersect?(b)   #=> true
+ *     a.intersect?(c)   #=> false
+ */
+
+static VALUE
+rb_ary_intersect_p(VALUE ary1, VALUE ary2)
+{
+    VALUE hash, v, result, shorter, longer;
+    st_data_t vv;
+    long i;
+
+    ary2 = to_ary(ary2);
+    if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
+
+    if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
+        for (i=0; i<RARRAY_LEN(ary1); i++) {
+            v = RARRAY_AREF(ary1, i);
+            if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
+        }
+        return Qfalse;
+    }
+
+    shorter = ary1;
+    longer = ary2;
+    if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
+        longer = ary1;
+        shorter = ary2;
+    }
+
+    hash = ary_make_hash(shorter);
+    result = Qfalse;
+
+    for (i=0; i<RARRAY_LEN(longer); i++) {
+        v = RARRAY_AREF(longer, i);
+        vv = (st_data_t)v;
+        if (rb_hash_stlike_lookup(hash, vv, 0)) {
+            result = Qtrue;
+            break;
+        }
+    }
+    ary_recycle_hash(hash);
+
+    return result;
+}
+
 static VALUE
 ary_max_generic(VALUE ary, long i, VALUE vmax)
 {
@@ -8295,6 +8350,7 @@ Init_Array(void) https://github.com/ruby/ruby/blob/trunk/array.c#L8350
     rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
     rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
     rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
+    rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
     rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
     rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
     rb_define_alias(rb_cArray,  "append", "push");
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 789531f..bf6a728 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -1100,6 +1100,19 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L1100
     assert_not_include(a, [1,2])
   end
 
+  def test_intersect?
+    a = @cls[ 1, 2, 3]
+    assert_send([a, :intersect?, [3]])
+    assert_not_send([a, :intersect?, [4]])
+    assert_not_send([a, :intersect?, []])
+  end
+
+  def test_intersect_big_array
+    assert_send([@cls[ 1, 4, 5 ]*64, :intersect?, @cls[ 1, 2, 3 ]*64])
+    assert_not_send([@cls[ 1, 2, 3 ]*64, :intersect?, @cls[ 4, 5, 6 ]*64])
+    assert_not_send([@cls[], :intersect?, @cls[ 1, 2, 3 ]*64])
+  end
+
   def test_index
     a = @cls[ 'cat', 99, /a/, 99, @cls[ 1, 2, 3] ]
     assert_equal(0, a.index('cat'))
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]