Project

General

Profile

Feature #12247 ยป delete_multi.patch

usa (Usaku NAKAMURA), 04/03/2016 09:45 AM

View differences:

array.c (working copy)
}
}
static VALUE
rb_ary_delete_internal(VALUE ary, VALUE item, int *deleted)
{
VALUE v = item;
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
VALUE e = RARRAY_AREF(ary, i1);
if (rb_equal(e, item)) {
v = e;
continue;
}
if (i1 != i2) {
rb_ary_store(ary, i2, e);
}
i2++;
}
if (RARRAY_LEN(ary) == i2) {
if (deleted) *deleted = 0;
if (rb_block_given_p()) {
return rb_yield(item);
}
return Qnil;
}
if (deleted) *deleted = 1;
ary_resize_smaller(ary, i2);
return v;
}
VALUE
rb_ary_delete(VALUE ary, VALUE item)
{
return rb_ary_delete_internal(ary, item, NULL);
}
/*
* call-seq:
* ary.delete(obj) -> item or nil
* ary.delete(obj) { block } -> item or result of block
* ary.delete(...) -> [items]
* ary.delete(...) { block } -> [items] or [results of block]
*
* Deletes all items from +self+ that are equal to +obj+.
*
......
* the item is not found. (To remove +nil+ elements and get an informative
* return value, use Array#compact!)
*
* If passed multiple arguments, delete them from +self+ and returns the
* deleted items as an Array. In this case, if no item is deleted, returns
* empty Array.
*
* a = [ "a", "b", "b", "b", "c" ]
* a.delete("b") #=> "b"
* a #=> ["a", "c"]
* a.delete("z") #=> nil
* a.delete("z") { "not found" } #=> "not found"
* a.delete("a", "c") #=> ["a", "c"]
* a #=> []
* a.delete("a", "c") #=> []
*/
VALUE
rb_ary_delete(VALUE ary, VALUE item)
static VALUE
rb_ary_delete_m(int argc, VALUE *argv, VALUE ary)
{
VALUE v = item;
long i1, i2;
switch (argc) {
case 0:
return Qnil;
case 1:
return rb_ary_delete_internal(ary, argv[0], NULL);
default:
{
VALUE r = rb_ary_new();
VALUE e;
int i;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
VALUE e = RARRAY_AREF(ary, i1);
if (rb_equal(e, item)) {
v = e;
continue;
for (i = 0; i < argc; i++) {
int deleted;
e = rb_ary_delete_internal(ary, argv[i], &deleted);
if (deleted || rb_block_given_p()) {
rb_ary_push(r, e);
}
if (i1 != i2) {
rb_ary_store(ary, i2, e);
}
i2++;
return r;
}
if (RARRAY_LEN(ary) == i2) {
if (rb_block_given_p()) {
return rb_yield(item);
}
return Qnil;
}
ary_resize_smaller(ary, i2);
return v;
}
void
rb_ary_delete_same(VALUE ary, VALUE item)
{
......
rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
rb_define_method(rb_cArray, "delete", rb_ary_delete_m, -1);
rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
test/ruby/test_array.rb (working copy)
a = @cls[1, o, o2, 2]
assert_equal(o2, a.delete(42))
assert_equal([1, 2], a)
a = @cls[*('cab'..'cat').to_a]
assert_equal(['cab', 'car'], a.delete('cab', 'car'))
assert_equal(@cls[*('cac'..'caq').to_a] + @cls[*('cas'..'cat').to_a], a)
a = @cls[*('cab'..'cat').to_a]
assert_equal(['cap'], a.delete('cap', 'caz'))
assert_equal(@cls[*('cab'..'cao').to_a] + @cls[*('caq'..'cat').to_a], a)
a = @cls[*('cab'..'cat').to_a]
assert_equal(nil, a.delete())
assert_equal(@cls[*('cab'..'cat').to_a], a)
a = @cls[*('cab'..'cat').to_a]
assert_equal(['cap', 99], a.delete('cap', 'caz') { 99 })
assert_equal(@cls[*('cab'..'cao').to_a] + @cls[*('caq'..'cat').to_a], a)
a = @cls[*('cab'..'cat').to_a]
assert_equal(['cap', nil], a.delete('cap', 'caz') { nil })
assert_equal(@cls[*('cab'..'cao').to_a] + @cls[*('caq'..'cat').to_a], a)
end
def test_delete_at
    (1-1/1)