如何初始化三维ruby数组

时间:2017-06-05 10:55:28

标签: arrays ruby

我想初始化一个三维ruby数组。对于二维数组,我可以做

a = Array.new(4){ Array.new(5, 0) }

所以我试过了

a = Array.new(4) { Array.new(5, Array.new(6, 0)) }

但如果我a[1][2][3] = 5,它不仅将该元素设置为5,而且将相应的元素设置为其他子数组中的5,即

[[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]],
 [[0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0]],
 [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]],
 [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]]

4 个答案:

答案 0 :(得分:4)

问题在于,如果将值作为参数传递,您将获得一个数组,其中每个值都引用同一个对象。你可以这样做:

Array.new(5, Array.new(6, 0))

您可以使用Array#*,即数组乘法:

[[[0] * 6] * 5] * 4

答案 1 :(得分:1)

对所有维度使用相同的语法(使用块而不是参数:Array.new(n){...})。

a = Array.new(4) { Array.new(5) { Array.new(6, 0) } }

这样,您的代码将创建20个区别Array.new(6, 0)子子数组,而不是复制相同的对象5次。

require 'pp'
a = Array.new(4) { Array.new(5) { Array.new(6, 0) } }
a[1][2][3] = 5
pp a
# [[[0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0]],
#  [[0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 5, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0]],
#  [[0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0]],
#  [[0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0],
#   [0, 0, 0, 0, 0, 0]]]

答案 2 :(得分:0)

以下工作正常。

a=Array.new(4){ Array.new(5) { Array.new(6,0) }}

答案 3 :(得分:0)

您可以使用递归来初始化任何维度的多维数组的元素。 1

<强>代码

def init(n, *rest)
  rest.empty? ? Array.new(n, 0) : Array.new(n) { init(*rest) }
end

<强>实施例

dims = [2, 3, 2]
a = init(*dims)
  #=> [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]

a[0][0][0] = 1
a #=> [[[1, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]

dims = [2, 3, 2, 4, 2, 3]
a = init(*dims)

a.flatten.size
  #=> 288 (= 2*3*2*4*2*3)
a[0][0][0][0][0][0] = 1
a.flatten.count(1)
  #=> 1

<强>解释

步骤如下。

假设,如示例中所示,

dims = [2, 3, 2]

然后

n, *rest = dims
  #=> [2, 3, 2]
n #=> 2
rest
  #=> [3, 2]

作为rest.empty? #=> false,方法返回

Array.new(2) { init(*[3, 2]) } # (1)
  #=> [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]

要获得此结果,我们执行块

{ init(*[3, 2]) }

对于正在构造的数组的两个元素中的每一个。这需要我们计算init([3, 2])(与{ init(3, 2) }相同),其操作如下。

n, *rest = [3, 2]
  #=> [3, 2]
n #=> 3
rest
  #=> [2]

再次,作为rest.empty? #=> false,我们返回

Array.new(3) { init(*[2]) } # (2)
  #=> [[0, 0], [0, 0], [0, 0]]

至上述表达式(1)。对于该数组的3个元素中的每一个,我们执行块

{ init(*[2]) }

这要求我们计算init([2]),其操作如下。

n, *rest = [2]
  #=> [2]
n #=> 2
rest 
  #=> []

这次,自rest.empty? #=> true起,我们计算并返回

Array.new(2, 0)
  #=> [0, 0]

到上面的表达式(2)。

1是的,没有&#34;多维数组&#34;在Ruby中,但我希望读者知道我的意思。替代方法类似于#34; ...包含大小相等的嵌套数组,包含任意数量的嵌套级别&#34;,但即使这样也不完整,因为它无法排除,例如,{{1} }。如果Ruby有这样的对象的名称,将会很有帮助。