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/