Array.reject !, how does it work?

Today I made a very small ruby ​​script that uses regular expressions to track specific content in files with a specific name and removes that content before adding its replacement. (Or else during iterations, everything will be wrong).

I'm not very used to ruby ​​(I’ve been using it only since the start of my vacation work, which is 1-2 weeks ago), but one of my habits is not to touch lists (or most other ADTs using indexes) during iterating over them (to remove specific content) it doesn't matter which language I use.

After some searching, I found out about a few features Arraythat might help. I am using right now Array.reject!, and the script works as if I want it to work, but I honestly cannot understand why it Array.reject! {|line| line =~ regex }does not have problems skipping objects in the array. These sources, ruby-docs and some random websites , confirm that the changes are applied instantly during the iteration, which makes me wonder how it will not go bad ... The lines that are deleted do not have spaces / words between them, only \nleads the next one on its own line (but this is only part of the end of the lines).

Has anyone got a great explanation for this?

+5
source share
2

Array#reject! for . C:

for (i = 0; i < RARRAY_LEN(ary); ) {
  VALUE v = RARRAY_PTR(ary)[i];
  if (RTEST(rb_yield(v))) {
    rb_ary_delete_at(ary, i);
    result = ary;
  } 
  else {
    i++;
  }
}

, i for. , reject!, true, , ary[i] . false, i .

[a b c d].reject! {|x| x == b}

 0 <------- i # doesn't match => i++
[a b c d]

   1 <----- i # matches => delete ary[i]
[a b c d]

   1 <----- i # doesn't match => i++
[a c d]

     2 <--- i # doesn't match => finished
[a c d]
+14

ary_reject_bang, C reject!.

static VALUE
ary_reject_bang(VALUE ary)
{
    long i;
    VALUE result = Qnil;

    rb_ary_modify_check(ary);
    for (i = 0; i < RARRAY_LEN(ary); ) {
        VALUE v = RARRAY_PTR(ary)[i];
        if (RTEST(rb_yield(v))) {
            rb_ary_delete_at(ary, i);
            result = ary;
        }
        else {
            i++;
        }
    }
    return result;
}

RARRAY_PTR - , ruby.h, C Ruby. rb_ary_delete_at, :

VALUE
rb_ary_delete_at(VALUE ary, long pos)
{
    long len = RARRAY_LEN(ary);
    VALUE del;

    if (pos >= len) return Qnil;
    if (pos < 0) {
        pos += len;
        if (pos < 0) return Qnil;
    }

    rb_ary_modify(ary);
    del = RARRAY_PTR(ary)[pos];
    MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
        RARRAY_LEN(ary)-pos-1);
    ARY_INCREASE_LEN(ary, -1);

    return del;
}
+2
source

All Articles