Hi --
I'm having a problem trying to wrap the zip method in a function.
If I put the following into irb:
[1,2,3].zip [4,5,6],[7,8,9],[10,11,12],[13,14,15]
I get:
=> [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]
Now I'm trying to wrap this into a function, where I can pass in an array of arrays as a parameter to get the same output. I have tried the following:
def transpose(matrix) matrix[0].zip matrix[1..-1] end
However when I pass the following into the function, I get a totally different result:
transpose([1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]) => [[1, [4, 5, 6]], [2, [7, 8, 9]], [3, [10, 11, 12]]]
If I assign the array of arrays to a variable:
m = [1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]
And then perform the operation manually, I get the correct result:
m[0].zip m[1],m[2],m[3],m[4] => [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]
I've been mucking around for half a day now, trying the get this damn thing to output correctly, but I'm not sure what I'm doing wrong.
I would like the output as above. Even better still would be the result repacked as per the original parameter:
=> [[1,4,7],[10,13,2],[5,8,11],[14,3,6],[9,12,15]]
Can anybody help me?
It's probably a better question for the ruby-talk list (general Ruby questions), but yes, I can help.
Arrays already have a transpose method:
irb(main):014:0> m => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]] irb(main):015:0> m.transpose => [[1, 4, 7, 10, 13], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]
If for some reason you need to roll your own, you'd need to do:
matrix[0].zip(*matrix[1..-1]) # note the * operator
Without the * you're doing this:
[1,2,3].zip([[4,5,6], [7,8,9], [10,11,12], [13,14,15]])
i.e., you're mapping 1,2,3 to an array with four elements. You really want to map it to four arrays; the * operator takes care of "un-arraying" the big array into a list of smaller arrays.
David