I need some clarification on how this 2D array can be created in Ruby?

Viewed 55

I'm currently learning Ruby through App Academy Open, and came across a problem that I solved differently than the course solution. I could use some clarification on how the course solution works.

We have to define a function "zip" that takes any number of arrays as arguments (but all arrays the same length). The function should return a 2D array where each subarray contains the elements at the same index from each argument.

zip(['a','b','c'],[1,2,3])

should return:

[['a',1],['b',2],['c',3]]

Here is my solution:

def zip(*arrs)
    main_arr = Array.new(arrs[0].length) {Array.new}

    arrs.each do |array|
        array.each_with_index do |ele, ele_idx|
            main_arr[ele_idx] << ele
        end
    end

    main_arr
end

And here is the course solution:

def zip(*arrays)
    length = arrays.first.length

    (0...length).map do |i|
        arrays.map { |array| array[i] }
    end
end

Can someone explain how the 2D array is being built within the mapped range above? I'm a bit confused as a beginner and could use some clarification.

EDIT:

Thank you very much iGian. Explanation really helped.

1 Answers

Running the code below should be self explanatory, see the comments:

def zip_steps(*arrays)
  # get the size of the array
  length = arrays.first.length

  # mapping the range up to use as indexing
  p (0...length).map { |i| i } #=> [0, 1, 2]

  # map the arrays
  p arrays.map { |array| array } #=> [["a", "b", "c"], [1, 2, 3]]

  # map the arrays returning a specific element at index 1, for example
  p arrays.map { |array| array[1] } #=> ["b", 2]

  # put arrays mapping inside the range mapping
  # where instead of returning the element 1
  # it returns the element i
  (0...length).map do |i|
    arrays.map { |array| array[i] }
  end

end

ary1 = ['a','b','c']
ary2 = [1,2,3]

p zip_steps(ary1, ary2) #=> [["a", 1], ["b", 2], ["c", 3]]
Related