ruby - Using self.dup, but failing rspec test to not modify original array -


i'm creating method transpose square 2-d arrays. method passes every test, except "does not modify original array" one. i'm working on duped array, i'm confused on why test failing.

code:

class array   def my_transpose     orig_arr = self.dup; array = []     orig_arr[0].length.times       temp_arr = []       orig_arr.each { |arr| temp_arr << arr.shift }       array << temp_arr     end     array   end end 

rspec:

describe array      describe "#my_transpose"         let(:arr) { [           [1, 2, 3],           [4, 5, 6],           [7, 8, 9]         ] }      let(:small_arr) { [       [1, 2],       [3, 4]     ] }      "transposes small matrix"       expect(small_arr.my_transpose).to eq([         [1, 3],         [2, 4]       ])     end      "transposes larger matrix"       expect(arr.my_transpose).to eq([         [1, 4, 7],         [2, 5, 8],         [3, 6, 9]       ])     end      "should not modify original array"       small_arr.my_transpose        expect(small_arr).to eq([         [1, 2],         [3, 4]       ])     end      "should not call built-in #transpose method"       expect(arr).not_to receive(:transpose)        arr.my_transpose     end   end end 

output:

  7) array#my_transpose should not modify original array      failure/error: expect(small_arr).to eq([         expected: [[1, 2], [3, 4]]             got: [[], []]         (compared using ==)      # ./spec/00_array_extensions_spec.rb:123:in `block (3 levels) in <top (required)>' 

when call dup on array, duplicates array itself; array's contents not duplicated. so, example:

a = [[1,2],[3,4]] b = a.dup a.object_id == b.object_id        # => false a[0].object_id == b[0].object_id  # => true 

thus, modifications a itself not reflected in b (and vice versa), modifications in elements of a reflected in b, because elements same objects.

that being case, problem crops here:

orig_arr.each { |arr| temp_arr << arr.shift } 

arr element of orig_arr, also element of self. if did remove it orig_arr, not remove self, if change it, it's changed, no matter how accessing it, , turns out, array#shift destructive operation.

probably smallest change make code make work expect use each_with_index, , use index arr, rather calling arr.shift, so:

orig_arr.each_with_index { |arr,i| temp_arr << arr[i] } 

in fact, though, once you're doing that, you're not doing destructive operations @ , don't need orig_arr, can use self.


Comments