Rubyで要素数が異なる配列をtransposeする6つの方法です。(ベンチマークとテスト付きです)
コード
require 'benchmark' require 'test/unit' module SafeTranspose refine Array do def a max_length = max_by(&:size).size map { |value| Array.new(max_length) { |i| value[i] || '' } }.transpose end def b max_length = max_by(&:size).size map { |m| m.fill('', m.size, max_length - m.size) }.transpose end # def c # # 先頭要素が最長である必要があるので却下 # self[0].zip(*self[1..-1]) # end def d max_length = max_by(&:size).size map { |e| e.values_at(0...max_length) }.transpose end def e max_length = max_by(&:size).size Array.new(max_length) { |i| map { |e| e[i] } } end def f result = [] max_size = max_by(&:size).size max_size.times do |i| result[i] = Array.new(first.size) each_with_index { |r, j| result[i][j] = r[i] } end result end end end using SafeTranspose array = [] 90000.times do array.push((1..rand(10)).to_a) end Benchmark.bm 10 do |r| ('a'..'f').to_a.each do |m| next if m == 'c' r.report m do array.send(m) end end end class SafeTransposeTest < Test::Unit::TestCase using SafeTranspose @@array = [] 10.times do @@array.push((1..rand(10)).to_a) end ('a'..'f').each do |m| next if m == 'c' define_method("test_#{m}") do assert_equal @@array.a, @@array.send(m) end end end
結果
user system total real a 0.180000 0.020000 0.200000 ( 0.203185) b 0.090000 0.000000 0.090000 ( 0.093895) d 0.110000 0.010000 0.120000 ( 0.116067) e 0.120000 0.000000 0.120000 ( 0.124450) f 0.190000 0.010000 0.200000 ( 0.195936) Loaded suite safe_transpose_test Started ..... Finished in 0.001421 seconds. --------------------------------------------------------------------------------------------------------------------------------------- 5 tests, 5 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 100% passed --------------------------------------------------------------------------------------------------------------------------------------- 3518.65 tests/s, 3518.65 assertions/s
コメントを残す