# Transposing a 2D array

Would you have any suggestions for improvements for the code below?

def my_transpose(arr)
# number of rows
m = arr.count

#number of columns
n = arr[0].count

transposed_arr = Array.new(n) { Array.new(m) }

# loop through the rows
arr.each_with_index do |row, index1|

# loop through the colons of one row
row.each_with_index do |num, index2|

# swap indexes to transpose the initial array
transposed_arr[index2][index1] = num
p transposed_arr
end
end
transposed_arr
end


As already mentioned, Ruby's Array comes with a built-in #transpose method.

But, for the purposes of an exercise, there are multiple ways to do the same thing.

For instance, one way (which only works for square matrices!) is to use #map:

def my_transpose(arr)
arr.each_with_index.map do |_, index|
arr.map { |row| row[index] }
end
end


Or you can use reduce (this will work for rectangular matrices):

def my_transpose(arr)
arr.reduce([]) do |transposed, row|
row.each_with_index do |value, col|
transposed[col] ||= []
transposed[col] << value
end
transposed
end
end


Or do basially the same thing, just using each_with_object:

def my_transpose(arr)
arr.each_with_object([]) do |row, transposed|
row.each_with_index do |value, col|
transposed[col] ||= []
transposed[col] << value
end
end
end


But keeping more of your code, you could use Array#new as your loop, since it accepts a block.

For instance:

def my_transpose(arr)
rows = arr.count
cols = arr.first.count
Array.new(cols) do |col|
Array.new(rows) do |row|
arr[row][col]
end
end
end


Of course, you'll want to check a few things. Firstly, whether there are any rows in the matrix at all (if not, the arr[0].count will fail), and whether the matrix is actually rectangular:

def my_transpose(arr)
return [] if arr.empty?

rows = arr.count
cols = arr.first.count

raise ArgumentError unless arr.all? { |row| row.count == cols }

Array.new(cols) do |col|
Array.new(rows) do |row|
arr[row][col]
end
end
end


There are yet more ways to do things, but again: It's already built in as arr.transpose.

• Thanks, looking at different ways to do things really help get a grasp of the language. Thx again! – Andrea.cabral Jun 12 '15 at 22:15

Array#transpose is a built-in Ruby method. Try instead:

p transposed_arr = arr.transpose

• Just to match what the original poster's code does. – Dan Kohn Apr 16 '15 at 11:40

As mentioned before transpose is a built-in which is fine if don't have space constraint O(N), but if you need O(1) you can do in-place transpose:

def transpose(matrix)
size = matrix[0].size # assumes square matrix
(0..(size - 2 )).to_a.each do |y|
(y..(size - 1)).to_a.each do |x|
matrix[y][x], matrix[x][y] = matrix[x][y], matrix[y][x]
end
end
end