将二维数组的子数组压缩在一起

时间:2014-04-02 13:01:25

标签: ruby arrays list

有没有一般的方法呢?

每个子数组的长度都相同。

c = [[1,1,1,1], [2,2,2,2], [3,3,3,3]]

c[0].zip(c[1], c[2])

=> [[1,2,3][1,2,3],[1,2,3],[1,2,3]]

谢谢。

2 个答案:

答案 0 :(得分:7)

使用zip执行此操作:

c.first.zip(*c.drop(1))

否则,

c.transpose

将是一种对称的方式。

答案 1 :(得分:3)

编辑:我发现为什么我的方法如此之快,这可能会带来好的和坏的含义,具体取决于结果的使用方式。假设

c = [[1,1,1],[2,2,2]]

然后

d = [c.map(&:first)]*c.first.size #=> [a, b, c]

其中:

a = b = c = [1,2]

但那是因为:

a.object_id = b.object_id = c.object.id

所以“坏”是如果d的元素被更改,则该行中的所有元素都将更改为相同的值。 “好”是如果数组d不会被更改,不仅这个方法很快,而且需要很少的存储来保存结果数组d的(表示)。

然而,事实是,如果不改变d,那么创建它是没有意义的。相反,应该重构代码,以便在后续操作中仅使用d的第一个元素。 (当然,这句话适用于所有方法。)

编辑结束

如果您希望c的每个元素(行)包含彼此相等的元素,并且它们的大小都相同(如您的示例中所示),则可以执行此操作:

[c.map(&:first)]*c.first.size

出于好奇,我决定对这种方法和@sawa提供的两种方法进行基准测试。

基准代码

require 'benchmark'

def sawa_zip(c)       c.first.zip(*c.drop(1))       end
def sawa_transpose(c) c.transpose                   end
def cary(c)           [c.map(&:first)]*c.first.size end

def bench_em(n, m, iterations)
  puts "n = #{n}, m = #{m}, interations = #{iterations}\n" 
  c = n.times.map { Array.new }.map.with_index { |_,i| Array.new(m,i) } 
  Benchmark.bm(%w[sawa_zip, sawa_transpose, cary].map(&:size).max) do |bm|

    bm.report('sawa_zip') do
      iterations.times do
        sawa_zip(c)
      end
    end

    bm.report('sawa_transpose') do
     iterations.times do
       sawa_transpose(c)
     end
    end

    bm.report('cary') do
      iterations.times do
        cary(c)
      end
    end
  end
end

bench_em(200, 300,5)
bench_em(2000, 3000,5)
bench_em(10000, 15000,1)

基准测试结果

应该记住,这种比较仅在矩阵每行中的所有元素相等时才有效。我曾预料到我建议的方法相对较快,但速度不如结果所示。

n = 200, m = 300, interations = 5
                      user     system      total        real
sawa_zip          0.010000   0.000000   0.010000 (  0.007858)
sawa_transpose    0.000000   0.000000   0.000000 (  0.006568)
cary              0.000000   0.000000   0.000000 (  0.000113)

n = 2000, m = 3000, interations = 5
                      user     system      total        real
sawa_zip          1.010000   0.070000   1.080000 (  1.080286)
sawa_transpose    0.800000   0.060000   0.860000 (  0.860823)
cary              0.000000   0.000000   0.000000 (  0.001669)

n = 10000, m = 15000, interations = 1
                      user     system      total        real
sawa_zip         25.760000   0.740000  26.500000 ( 26.668127)
sawa_transpose   18.200000   0.630000  18.830000 ( 18.870150)
cary              0.000000   0.000000   0.000000 (  0.002412)