Ruby_Array_32

この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。

class Array (Ruby 3.0.0 リファレンスマニュアル)

インスタンスメソッド

intersection(*other_arrays) -> Array
  • 自身と引数に渡された配列の共通要素を新しい配列として返す
    • 要素が重複する場合は、そのうち1つのみを返す
    • 要素の順序は自身の順序を維持する
irb(main):001:0> arr = [1, 1, 3, 5]
=> [1, 1, 3, 5]

irb(main):002:0> brr = [3, 2, 1]
=> [3, 2, 1]

irb(main):003:0> arr.intersection(brr)
=> [1, 3]

irb(main):004:0> arr
=> [1, 1, 3, 5]

irb(main):005:0> brr
=> [3, 2, 1]

irb(main):006:0> [5, 3, 1, 1].intersection([3, 2, 1])
=> [3, 1]
irb(main):001:0> [1, 2, 3, 'a', 'b', 'c'].intersection([2, 'a'], [1, 'a', 'c'])
=> ["a"]
iirb(main):001:0> arr = [1, 2, 3]
=> [1, 2, 3]

irb(main):002:0> brr = arr.intersection
=> [1, 2, 3]

irb(main):003:0> brr[1] = 'a'
=> "a"

irb(main):004:0> arr
=> [1, 2, 3]

irb(main):005:0> brr
=> [1, "a", 3]

# memo
# 後述の内部実装を見ても、引数がないときはforが実行されないので実質コピーしたものを返すようだ
# intersectionは内部で&の処理を順番に呼び出しているみたいだ

[1] pry(main)> require 'pry-doc'
=> true

[2] pry(main)> show-source Array#&

From: array.c (C Method):
Owner: Array
Visibility: public
Signature: &(arg1)
Number of lines: 34

static VALUE
rb_ary_and(VALUE ary1, VALUE ary2)
{
    VALUE hash, ary3, v;
    st_data_t vv;
    long i;

    ary2 = to_ary(ary2);
    ary3 = rb_ary_new();
    if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;

    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)) continue;
            if (rb_ary_includes_by_eql(ary3, v)) continue;
            rb_ary_push(ary3, v);
        }
        return ary3;
    }

    hash = ary_make_hash(ary2);

    for (i=0; i<RARRAY_LEN(ary1); i++) {
        v = RARRAY_AREF(ary1, i);
        vv = (st_data_t)v;
        if (rb_hash_stlike_delete(hash, &vv, 0)) {
            rb_ary_push(ary3, v);
        }
    }
    ary_recycle_hash(hash);

    return ary3;
}

[3] pry(main)> show-source Array#intersection

From: array.c (C Method):
Owner: Array
Visibility: public
Signature: intersection(*arg1)
Number of lines: 12

static VALUE
rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
{
    VALUE result = rb_ary_dup(ary);
    int i;

    for (i = 0; i < argc; i++) {
        result = rb_ary_and(result, argv[i]);
    }

    return result;
}