简体   繁体   English

如何初始化三维ruby数组

[英]How to initialise a three dimensional ruby array

I want to initialise a three dimensional ruby array. 我想初始化一个三维红宝石阵列。 For a two-dimensional array, I can do 对于二维数组,我可以做到

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

so I have tried 所以我试过了

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

but if I do a[1][2][3] = 5 , it not only sets that element to 5 , it sets the corresponding element to 5 in other sub arrays ie 但如果我做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]]]

The issue is that if you pass the value as an argument, you will get an array where each value refers to that same object. 问题是,如果将值作为参数传递,您将获得一个数组,其中每个值引用同一个对象。 You do exactly that with: 你这样做:

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

You can use Array#* , ie array multiplication instead: 你可以使用Array#* ,即数组乘法:

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

Just use the same syntax (with a block instead of an argument : Array.new(n){...} ) for all the dimensions. 只需对所有维使用相同的语法(使用块而不是参数: Array.new(n){...} )。

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

This way, your code will create 20 distincts Array.new(6, 0) sub-sub-arrays instead of replicating the same object 5 times. 这样,您的代码将创建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]]]

以下工作正常。

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

You can use recursion to initialize the elements of a multidimensional array of any dimension. 您可以使用递归来初始化任何维度的多维数组的元素。 1 1

Code

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

Examples 例子

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

Explanation 说明

The steps are as follows. 步骤如下。

Suppose, as in the example, 假设,如示例中所示,

dims = [2, 3, 2]

Then 然后

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

As rest.empty? #=> false 作为rest.empty? #=> false rest.empty? #=> false , the method returns rest.empty? #=> false ,方法返回

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

To obtain this result, we execute the block 为了获得这个结果,我们执行块

{ init(*[3, 2]) }

for each of the two elements of the array being constructed. 对于正在构造的数组的两个元素中的每一个。 This requires us to compute init([3, 2]) (same as { init(3, 2) } ), which is done as follows. 这需要我们计算init([3, 2]) (与{ init(3, 2) } ),其完成如下。

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

Again, as rest.empty? #=> false 再次,作为rest.empty? #=> false rest.empty? #=> false , we return rest.empty? #=> false ,我们回来了

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

to expression (1) above. 表达式(1)。 For each of the 3 elements of this array we execute the block 对于该数组的3个元素中的每一个,我们执行该块

{ init(*[2]) }

This requires us to compute init([2]) , which is done as follows. 这需要我们计算init([2]) ,其完成如下。

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

This time, since rest.empty? #=> true 这一次,因为rest.empty? #=> true rest.empty? #=> true , we compute and return rest.empty? #=> true ,我们计算并返回

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

to expression (2) above. 表达式(2)。

1 Yes, there's no such thing as a "multidimensional array" in Ruby, but I expect readers to know what I mean. 1是的,Ruby中没有“多维数组”这样的东西,但我希望读者知道我的意思。 The alternative is something like "...of an array containing nested arrays of equal size with any number of levels of nesting", but even that is incomplete as it fails to exclude, for example, [[1, [2,3]], [4,5]] . 替代方案类似于“...包含大小相等且具有任意数量嵌套级别的嵌套数组的数组”,但即使这样也不完整,因为它无法排除,例如, [[1, [2,3]], [4,5]] It would be helpful if Ruby had a name for such objects. 如果Ruby有这样的对象的名称将是有帮助的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM