在Ruby中初始化2d数组

时间:2015-03-16 18:55:08

标签: ruby arrays

我想要一个2d数组初始化如下

1 0 0 0
0 2 0 0
0 0 3 0
0 0 0 4

给出输入字符串"1234"时。

我的功能如下

def fun(str)
    maxlength = Array.new(str.length,Array.new(str.length,0))
    (0..str.length-1).each do |i|
        maxlength[i][i] = str[i].to_i
    end
    print maxlength
end

print fun("1234")

这给了我

1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4

这不是我想要的。

如何获得我想要的输出?

3 个答案:

答案 0 :(得分:7)

我建议你使用类方法Matrix::diagonal

require 'Matrix'

str = "1234"

Matrix.diagonal(*(str.chars.map(&:to_i))).to_a
  # => [[1, 0, 0, 0],
  #     [0, 2, 0, 0],
  #     [0, 0, 3, 0],
  #     [0, 0, 0, 4]] 

另一种方式:

Array.new(str.size) {|i| Array.new(str.size) {|j| (i==j) ? str[i].to_i : 0}}
  # => [[1, 0, 0, 0],
  #     [0, 2, 0, 0],
  #     [0, 0, 3, 0],
  #     [0, 0, 0, 4]] 

答案 1 :(得分:5)

这里最大的问题是你不是像你想象的那样创建一个二维数组,而是你正在创建两个数组。这是因为你将一个奇异的数组作为默认值传入,而不是一个可以生成它们的块。

你期待的是:

array1 = [ array21, array22, array23, array24 ]

你实际得到的是:

array1 = [ array2, array2, array2, array2 ]

通过将最后一个参数转换为块来轻松修复:

def fun(str)
    maxlength = Array.new(str.length) { Array.new(str.length,0) }
    str.chars.collect(&:to_i).each_with_index do |v,i|
        maxlength[i][i] = v
    end
    print maxlength
end

print fun("1234")

我也转而使用chars,根据需要拆分字符串。

所以问题是你正确设置了位置,但由于所有二级数组都是同一个数组,你没有得到你期望的结果。

更新:在Chris的回答中添加了each_with_index,这使得这项工作可以使用任意数字。

答案 2 :(得分:2)

另一个单行代表:

"1234".chars.map.with_index {|v, i| Array.new(4, 0).tap {|a| a[i] = v.to_i } }

这只创建N个数组,每个字符对应一个字符串,并将每个数组的i索引设置为字符串中该字符的值。

编辑:另一个有趣的解决方案:

"1234".chars.map.with_index {|c, i| [c.to_i].fill(0, 1..4).rotate(-i) }

这会创建四个由[value, 0, 0, 0]组成的数组,然后使用Array#rotate将值移动到正确的位置。

另一个解决方案,它利用了每对非零值之间有四个0值的事实:

"1234".chars.flat_map {|c| [c.to_i].fill(0, 1..4) }.each_slice(4).take(4)