Project

General

Profile

Feature #11315 ยป array_xor_recycle_seen.patch

0x0dea (D.E. Akers), 06/28/2015 05:07 PM

View differences:

array.c
4200 4200
    return ary3;
4201 4201
}
4202
/*
4203
 *  call-seq:
4204
 *     ary ^ other_ary     -> new_ary
4205
 *
4206
 *  Symmetric Difference --- Returns a new array containing the elements
4207
 *  which appear in either +ary+ or +other_ary+, but not both. The order
4208
 *  is preserved from the original array.
4209
 *
4210
 *  It compares elements using their #hash and #eql? methods for efficiency.
4211
 *
4212
 *     [1, 2, 3] ^ [2, 3, 4]      # => [1, 4]
4213
 *     %w[a b c] ^ %w[b c d d]    # => ["a", "d"]
4214
 *
4215
 *  If you need set-like behavior, see the library class Set.
4216
 */
4217

  
4218
static VALUE
4219
rb_ary_xor(VALUE ary1, VALUE ary2)
4220
{
4221
    VALUE seen, result, ary3;
4222
    st_data_t elt;
4223
    long i;
4224

  
4225
    ary2 = to_ary(ary2);
4226
    seen = rb_hash_new();
4227
    result = ary_make_hash(ary1);
4228

  
4229
    for (i = 0; i < RARRAY_LEN(ary2); ++i) {
4230
    elt = (st_data_t)RARRAY_AREF(ary2, i);
4231
    if (st_lookup(RHASH_TBL_RAW(seen), elt, 0)) continue;
4232
    st_update(RHASH_TBL_RAW(seen), elt, ary_hash_orset, elt);
4233
    if (st_lookup(RHASH_TBL_RAW(result), elt, 0)) {
4234
        st_delete(RHASH_TBL_RAW(result), &elt, 0);
4235
    }
4236
    else {
4237
        st_update(RHASH_TBL_RAW(result), elt, ary_hash_orset, elt);
4238
    }
4239
    }
4240

  
4241
    ary3 = rb_hash_values(result);
4242
    ary_recycle_hash(result);
4243
    ary_recycle_hash(seen);
4244
    return ary3;
4245
}
4246

  
4202 4247
static int
4203 4248
push_value(st_data_t key, st_data_t val, st_data_t ary)
4204 4249
{
......
5862 5906
    rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
5863 5907
    rb_define_method(rb_cArray, "&", rb_ary_and, 1);
5864 5908
    rb_define_method(rb_cArray, "|", rb_ary_or, 1);
5909
    rb_define_method(rb_cArray, "^", rb_ary_xor, 1);
5865 5910
    rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
5866 5911
    rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
test/ruby/test_array.rb
1724 1724
    assert_equal([obj1], [obj1]|[obj2])
1725 1725
  end
1726
  def test_XOR
1727
    assert_equal(@cls[],  @cls[]  ^ @cls[])
1728
    assert_equal(@cls[1], @cls[1] ^ @cls[])
1729
    assert_equal(@cls[1], @cls[]  ^ @cls[1])
1730
    assert_equal(@cls[],  @cls[1] ^ @cls[1])
1731

  
1732
    assert_equal(@cls[1,2], @cls[1] ^ @cls[2])
1733
    assert_equal(@cls[1,4], @cls[1,2,3] ^ @cls[2,3,4])
1734
    assert_equal(@cls[1,4], @cls[1,1,2,3] ^ @cls[2,3,4,4])
1735
  end
1736

  
1726 1737
  def test_combination
1727 1738
    assert_equal(@cls[[]], @cls[1,2,3,4].combination(0).to_a)
1728 1739
    assert_equal(@cls[[1],[2],[3],[4]], @cls[1,2,3,4].combination(1).to_a)