Project

General

Profile

Feature #11315 ยป array_xor_vodka.patch

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

View differences:

array.c
4200 4200
    return ary3;
4201 4201
}
4202 4202

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

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

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

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

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

  
4203 4247
static int
4204 4248
push_value(st_data_t key, st_data_t val, st_data_t ary)
4205 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

  
5866 5911
    rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
5867 5912
    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 1726

  
1727
  def test_XOR
1728
    assert_equal(@cls[],  @cls[]  ^ @cls[])
1729
    assert_equal(@cls[1], @cls[1] ^ @cls[])
1730
    assert_equal(@cls[1], @cls[]  ^ @cls[1])
1731
    assert_equal(@cls[],  @cls[1] ^ @cls[1])
1732

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

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