在Ruby中创建二维数组和访问子数组

gmi*_*ile 66 ruby arrays multidimensional-array

我想知道是否有可能创建一个二维数组并快速访问其中的任何水平或垂直子数组?

我相信在以下情况下我们可以访问水平子数组:

x = Array.new(10) { Array.new(20) }

x[6][3..8] = 'something'
Run Code Online (Sandbox Code Playgroud)

但据我了解,我们无法像这样访问它:

x[3..8][6]
Run Code Online (Sandbox Code Playgroud)

我怎样才能避免或破解这个限制?

joh*_*nes 95

Arrays你实现它们的方式存在二维问题.

a= [[1,2],[3,4]]
a[0][2]= 5 # works
a[2][0]= 6 # error
Run Code Online (Sandbox Code Playgroud)

HashArray

我更喜欢Hashes用于多维度Arrays

a= Hash.new
a[[1,2]]= 23
a[[5,6]]= 42
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,您不必手动创建列或行.插入哈希几乎是O(1),所以这里没有任何缺点,只要你Hash不会变得太大.

您甚至可以为所有未指定的元素设置默认值

a= Hash.new(0)
Run Code Online (Sandbox Code Playgroud)

所以现在关于如何获得子阵列

(3..5).to_a.product([2]).collect { |index| a[index] }
[2].product((3..5).to_a).collect { |index| a[index] }
Run Code Online (Sandbox Code Playgroud)

(a..b).to_a在O(n)中运行.从a中检索元素Hash几乎是O(1),因此集合几乎以O(n)运行.没有办法让它比O(n)更快,因为复制n个元素总是O(n).

Hashes当他们变得太大时会有问题.Array如果我知道我的数据量越来越大,那么我会考虑实现这样的多维度.

  • 这是旧的但是'a [2] [0]`一个错误,因为还没有创建第三个元素?意思是'a [1] [0] = 6`会起作用吗?我知道这已经老了......刚才看看Ruby. (4认同)

sha*_*jan 32

rows, cols = x,y  # your values
grid = Array.new(rows) { Array.new(cols) }
Run Code Online (Sandbox Code Playgroud)

至于访问元素,本文非常适合逐步地以您希望的方式封装数组:

如何ruby数组


Mar*_*une 30

你没有陈述你的实际目标,但也许这有助于:

require 'matrix'  # bundled with Ruby
m = Matrix[
 [1, 2, 3],
 [4, 5, 6]
]

m.column(0) # ==> Vector[1, 4]
Run Code Online (Sandbox Code Playgroud)

(和矢量就像数组一样)

或者,使用您想要的类似符号:

m.minor(0..1, 2..2) # => Matrix[[3], [6]]
Run Code Online (Sandbox Code Playgroud)

  • 读完这个答案之后,我开始使用`Matrix`,这很棒.但是,在转向"矩阵"之前,最好记住一个很大的限制 - 它们是不可变的.所以,没有办法修改单个元素,即`m(0,0)= 0#=> error` (6认同)
  • @GregoryGoltsov:给Marc-André+1写"矩阵".至于他们的不变性,我不会把它称为限制,而是一个功能.显然,Marc-Anré不仅让自己的生活更轻松,而且还将矩阵呈现为数字的概括. (2认同)

Mar*_*sel 11

这是一个3D阵列案例

class Array3D
   def initialize(d1,d2,d3)
    @data = Array.new(d1) { Array.new(d2) { Array.new(d3) } }
   end

  def [](x, y, z)
    @data[x][y][z]
  end

  def []=(x, y, z, value)
    @data[x][y][z] = value
  end
end
Run Code Online (Sandbox Code Playgroud)

您可以像访问任何其他Ruby数组一样访问每个数组的子部分.@data [0..2] [3..5] [8..10] = 0等


pie*_*fou 5

x.transpose[6][3..8]或者x[3..8].map {|r| r [6]}会给你想要的东西.

例:

a = [ [1,  2,  3,  4,  5],
      [6,  7,  8,  9,  10],
      [11, 12, 13, 14, 15],
      [21, 22, 23, 24, 25]
    ]

#a[1..2][2]  -> [8,13]
puts a.transpose[2][1..2].inspect   # [8,13]
puts a[1..2].map {|r| r[2]}.inspect  # [8,13]
Run Code Online (Sandbox Code Playgroud)