public
Created

Array#transpose that accepts a block for populating missing elements

  • Download Gist
transpose.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
class Array
 
# A more meaningful message when you have an insufficient number of columns
# in a row for transposition.
MSG_TRANSPOSE_INDEX_ERROR = "Row %s has only %s element(s), but transposition
requires %s. Please specify a block to populate missing items or adjust
your array to contain an equal number of elements in each row array."
 
# Overrides the default transpose method to allow a block that can be used to return
# elements required to populate the transposition.
# @example Using Transpose
# > [[1, 2], [3, 4]].transpose
# => [[1, 3], [2, 4]]
#
# > [[1], [3, 4]].transpose
# IndexError: Row 0 has only 1 element(s), but transposition requires 2...
#
# > [[1,], [3, 4]].transpose { |x, y| 2 }
# => [[1, 3], [2, 4]]
# @note
# When yielding to the block the column(x) and row(y) index for the
# missing element are provided
# @return [Array] The transposed array
def transpose
return clone if size == 0
rows = size
columns = map(&:size).max
result = Array.new(columns) { Array.new(rows) }
 
0...rows.times do |row_index|
0...columns.times do |column_index|
datum = if self[row_index].size > column_index
self[row_index][column_index]
elsif block_given?
yield(column_index, row_index)
else
raise IndexError, MSG_TRANSPOSE_INDEX_ERROR %
[row_index,
self[row_index].size,
columns]
end
result[column_index][row_index] = datum
end
end
 
result
end
end
 
require 'test/unit'
 
class TestArray < Test::Unit::TestCase
 
def test_transpose_empty
assert(Array.new.transpose.is_a?(Array))
end
 
def test_transpose_simple
assert_equal([[1, 2], [3, 4]].transpose,
[[1, 3], [2, 4]])
end
 
def test_transpose_with_block
filled = [[1], [3, 4]].transpose { |x, y| 2 }
assert_equal([[1, 3],[2, 4]], filled)
end
 
def test_your_array_sucks
assert_raise(IndexError) do
[[1, 2], [1]].transpose
end
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.