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

Ruby 将二维数组的子数组压缩在一起,ruby,arrays,list,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]] 谢谢。要使用zip: c.first.zip(*c.drop(1)) 否则, c.transpose 将是一种对称方式。要使用zip: c.first.zip(*c.drop(1)) 否则, c.transpose 将是一种对称的方式。编辑:我发

有没有一种通用的方法

每个子数组的长度相同

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]]

谢谢。

要使用
zip

c.first.zip(*c.drop(1))
否则,

c.transpose

将是一种对称方式。

要使用
zip

c.first.zip(*c.drop(1))
否则,

c.transpose

将是一种对称的方式。

编辑:我发现了为什么我的方法如此快速,这可能会产生好的和坏的影响,这取决于结果的使用方式。假设

c = [[1,1,1],[2,2,2]]
然后

其中:

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)

编辑:我发现了为什么我的方法如此之快,这可能有好有坏的影响,这取决于结果的使用方式。假设

c = [[1,1,1],[2,2,2]]
然后

其中:

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)

c
中的数组总是大小相同的?
c。转置
是您所需要的全部,即使您选择了一个答案,请回答@toro2k的问题,并回答另一个问题:您是否希望c的每一行都有相等的元素(例如,[2,2,2,2,2]?我这样问是因为我刚刚发布的答案是另一种方式,如果你的答案是“是”,那么你可以做你想做的事情对于这两个问题。更一般地说,因为其他人将来会阅读您的问题,所以清楚一点很重要。
c
中的数组总是大小相同?
c。即使您选择了一个答案,也只需要转置,请回答@toro2k的问题,还有一个问题:您是否打算让c的每一行都有相等的e元素(例如,[2,2,2,2]?我这样问是因为我刚才发布的答案是另一种方式,如果你的答案是“是”,那么你可以做你想做的事情对于这两个问题。更一般地说,正如其他人将来会阅读你的问题一样,清楚是很重要的。
#zip
是好的和安全的。
#转置
不安全,如果数组大小不同。+1表示
#zip
。太好了。谢谢。
#zip
是好的和安全的。
#转置
不安全,如果数组不安全大小不一..+1用于
#zip
。太棒了。谢谢。