2016-02-11 18 views
7

Hôm nay tôi tình cờ gặp một số hành vi kỳ lạ của phân tử mảng:hành vi kỳ lạ của phân tử mảng

arr = ["a","b"] 
arr2 = [1,2] 
arr.unshift(arr2) #= [[1, 2], "a", "b"] 
arr.push(arr2) #=> ["a", "b", [1, 2]] 

này có ý nghĩa, tuy nhiên:

arr[0,0] = arr2 #=> [1, 2, "a", "b"] 

Tôi biết rằng trong [0,0] số không đầu tiên là index và thứ hai là số phần tử được thực hiện trong mảng đó bắt đầu từ index.

Trong suy nghĩ của tôi, nó phải giống như unshift, nhưng không phải.

Có thể ai giải thích về hành vi không?

+1

Tại sao bạn nghĩ '[]' nên làm việc theo cách giống như 'unshift'? Họ là những phương pháp khác nhau. – sawa

+0

@sawa bạn nói đúng, đó chỉ là một điều, nhưng bạn có thể giải thích hành vi [0,0] không. Nó khá khác nhau – ImranNaqvi

+0

Tôi tin rằng tài liệu cho [Array # [\] =] (http://ruby-doc.org/core-2.2.0/Array.html#method-i-5B-5D-3D) là khá clear: "' ary [start, length] = obj' ... thay thế một subarray [với các phần tử 'obj'] từ chỉ mục' start' cho các phần tử 'length'". Ở đây bạn có thể tìm thấy rõ ràng hơn để viết 'arr.insert (0, arr2)'. (Nếu bạn muốn chèn 'arr2' vào cuối' arr', bạn có thể viết 'arr [arr.size, 0] = arr2' hoặc' arr.insert (arr.size, * arr2) '). Lưu ý song song với [str \ [fixnum, fixnum \] = new_str] (http://ruby-doc.org/core-2.2.0/String.html#method-i-5B-5D-3D). –

Trả lời

2

Nếu chúng ta dive into the ruby source code, chúng tôi sẽ tìm thấy một hàm có tên gọi khi array assignment happens với ba đối số (ví dụ: chỉ số, chiều dài, và giá trị mới):

static VALUE 
rb_ary_aset(int argc, VALUE *argv, VALUE ary) 
{ 
    long offset, beg, len; 

    if (argc == 3) { 
     rb_ary_modify_check(ary); 
     beg = NUM2LONG(argv[0]); 
     len = NUM2LONG(argv[1]); 
     rb_ary_splice(ary, beg, len, argv[2]); 
     return argv[2]; 
    } 
[...] 

Và nếu chúng ta theo cùng trong rb_ary_splice chúng tôi sẽ xảy ra khi mà sự kỳ diệu xảy ra:

static void 
rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) 
{ 
    long rlen; 
    long olen; 

    if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len); 
    olen = RARRAY_LEN(ary); 

    [...] 

     if (len != rlen) { 
      RARRAY_PTR_USE(ary, ptr, 
        MEMMOVE(ptr + beg + rlen, ptr + beg + len, 
         VALUE, olen - (beg + len))); 
      ARY_SET_LEN(ary, alen); 
     } 
     if (rlen > 0) { 
      MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_CONST_PTR(rpl), VALUE, rlen); 
     } 
    } 
    RB_GC_GUARD(rpl); 
} 

Đầu tiên nó làm cho căn phòng trong mảng cho các yếu tố mới và cập nhật chiều dài:

01.235.
RARRAY_PTR_USE(ary, ptr, 
    MEMMOVE(ptr + beg + rlen, ptr + beg + len, 
     VALUE, olen - (beg + len))); 
ARY_SET_LEN(ary, alen); 

Sau đó, thông qua sự kỳ diệu của con trỏ C, nó chèn các yếu tố mới (s):

MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_CONST_PTR(rpl), VALUE, rlen);