Project

General

Profile

Feature #11315 » array_xor_recycle_seen.patch

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

View differences:

array.c
return ary3;
}
/*
* call-seq:
* ary ^ other_ary -> new_ary
*
* Symmetric Difference --- Returns a new array containing the elements
* which appear in either +ary+ or +other_ary+, but not both. The order
* is preserved from the original array.
*
* It compares elements using their #hash and #eql? methods for efficiency.
*
* [1, 2, 3] ^ [2, 3, 4] # => [1, 4]
* %w[a b c] ^ %w[b c d d] # => ["a", "d"]
*
* If you need set-like behavior, see the library class Set.
*/
static VALUE
rb_ary_xor(VALUE ary1, VALUE ary2)
{
VALUE seen, result, ary3;
st_data_t elt;
long i;
ary2 = to_ary(ary2);
seen = rb_hash_new();
result = ary_make_hash(ary1);
for (i = 0; i < RARRAY_LEN(ary2); ++i) {
elt = (st_data_t)RARRAY_AREF(ary2, i);
if (st_lookup(RHASH_TBL_RAW(seen), elt, 0)) continue;
st_update(RHASH_TBL_RAW(seen), elt, ary_hash_orset, elt);
if (st_lookup(RHASH_TBL_RAW(result), elt, 0)) {
st_delete(RHASH_TBL_RAW(result), &elt, 0);
}
else {
st_update(RHASH_TBL_RAW(result), elt, ary_hash_orset, elt);
}
}
ary3 = rb_hash_values(result);
ary_recycle_hash(result);
ary_recycle_hash(seen);
return ary3;
}
static int
push_value(st_data_t key, st_data_t val, st_data_t ary)
{
......
rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
rb_define_method(rb_cArray, "&", rb_ary_and, 1);
rb_define_method(rb_cArray, "|", rb_ary_or, 1);
rb_define_method(rb_cArray, "^", rb_ary_xor, 1);
rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
test/ruby/test_array.rb
assert_equal([obj1], [obj1]|[obj2])
end
def test_XOR
assert_equal(@cls[], @cls[] ^ @cls[])
assert_equal(@cls[1], @cls[1] ^ @cls[])
assert_equal(@cls[1], @cls[] ^ @cls[1])
assert_equal(@cls[], @cls[1] ^ @cls[1])
assert_equal(@cls[1,2], @cls[1] ^ @cls[2])
assert_equal(@cls[1,4], @cls[1,2,3] ^ @cls[2,3,4])
assert_equal(@cls[1,4], @cls[1,1,2,3] ^ @cls[2,3,4,4])
end
def test_combination
assert_equal(@cls[[]], @cls[1,2,3,4].combination(0).to_a)
assert_equal(@cls[[1],[2],[3],[4]], @cls[1,2,3,4].combination(1).to_a)
(3-3/3)