【发布时间】:2011-10-24 06:01:13
【问题描述】:
也许问题在于我缺乏在这里找到东西的能力,但我找不到任何关于如何在 Ruby 中创建多维数组的信息。
谁能给我一个例子来说明如何做到这一点?
【问题讨论】:
标签: ruby multidimensional-array
也许问题在于我缺乏在这里找到东西的能力,但我找不到任何关于如何在 Ruby 中创建多维数组的信息。
谁能给我一个例子来说明如何做到这一点?
【问题讨论】:
标签: ruby multidimensional-array
严格来说,在 Ruby 中创建多维数组是不可能的。但是可以把一个数组放到另外一个数组里面,和多维数组差不多。
这是在 Ruby 中创建二维数组的方法:
a = [[1,2,3], [4,5,6], [7,8,9]]
require 'narray'
b = NArray[ [1,2,3], [4,5,6], [7,8,9] ]
使用a[i][j] 访问数组的元素。基本上a[i] 返回存储在a 的位置i 上的“子数组”,因此a[i][j] 从存储在位置i 的数组中返回元素编号j。
【讨论】:
a[1][2][1] 而不是 a[1,2,1],正如某些人所期望的那样。
您可以将块传递给Array.new
Array.new(n) {Array.new(n,default_value)}
返回块的值将是第一个数组的每个索引的值,
所以..
Array.new(2) {Array.new(2,5)} #=> [[5,5],[5,5]]
你可以使用array[x][y]访问这个数组
同样对于第二个 Array 实例化,您也可以将一个块作为默认值传递。所以
Array.new(2) { Array.new(3) { |index| index ** 2} } #=> [[0, 1, 4], [0, 1, 4]]
【讨论】:
(Array.new{Array.new})[2][2] = :value # => NoMethodError: undefined method '[]=' for nil:NilClass
只是一个澄清:
arr = Array.new(2) {Array.new(2,5)} #=> [[5,5],[5,5]]
根本不一样:
arr = Array.new(2, Array.new(2, 5))
在后一种情况下,尝试:
arr[0][0] = 99
这就是你得到的:
[[99,5], [99,5]]
【讨论】:
有两种方法可以初始化多数组(大小为 2)。 所有其他答案均显示具有默认值的示例。
声明每个子数组(你可以在运行时这样做):
multi = []
multi[0] = []
multi[1] = []
或在初始化时声明父数组的大小:
multi = Array.new(2) { Array.new }
使用示例:
multi[0][0] = 'a'
multi[0][1] = 'b'
multi[1][0] = 'c'
multi[1][1] = 'd'
p multi # [["a", "b"], ["c", "d"]]
p multi[1][0] # "c"
所以你可以把第一种方式包装起来,像这样使用:
@multi = []
def multi(x, y, value)
@multi[x] ||= []
@multi[x][y] = value
end
multi(0, 0, 'a')
multi(0, 1, 'b')
multi(1, 0, 'c')
multi(1, 1, 'd')
p @multi # [["a", "b"], ["c", "d"]]
p @multi[1][0] # "c"
【讨论】:
上面给出的方法不起作用。
n = 10
arr = Array.new(n, Array.new(n, Array.new(n,0.0)))
arr[0][1][2] += 1
puts arr[0][2][2]
等价于
n = 10
a = Array.new(n,0.0)
b = Array.new(n,a)
arr = Array.new(n, b)
arr[0][1][2] += 1
puts arr[0][2][2]
并且将打印 1.0,而不是 0.0,因为我们正在修改数组 a 并打印数组 a 的元素。
【讨论】:
其实这比上面给出的block方法快很多:
arr = Array.new(n, Array.new(n, Array.new(n,0.0)))
arr[0][1][2] += 1
【讨论】:
a = Array.new(2, Array.new(2, 0.0)); a[0][1] = 5; a # => [[0.0, 5], [0.0, 5]] 5 出现在索引 [0][1] 和 [1][1] 上,即使它只设置了一次。
我最近不得不在 Ruby 中重现 PHP 风格的多维数组。这是我所做的:
# Produce PHP-style multidimensional array.
#
# Example
#
# arr = Marray.new
#
# arr[1][2][3] = "foo"
# => "foo"
#
# arr[1][2][3]
# => "foo"
class Marray < Array
def [](i)
super.nil? ? self[i] = Marray.new : super
end
end
【讨论】:
也许您可以使用哈希来模拟您的多维数组。 Hash-key 可以是任何 Ruby 对象,所以你也可以使用一个数组。
例子:
marray = {}
p marray[[1,2]] #-> nil
marray[[1,2]] = :a
p marray[[1,2]] #-> :a
基于这个想法,您可以定义一个新类。
只是一个简单的场景:
=begin rdoc
Define a multidimensional array.
The keys must be Fixnum.
The following features from Array are not supported:
* negative keys (Like Array[-1])
* No methods <<, each, ...
=end
class MArray
INFINITY = Float::INFINITY
=begin rdoc
=end
def initialize(dimensions=2, *limits)
@dimensions = dimensions
raise ArgumentError if limits.size > dimensions
@limits = []
0.upto(@dimensions-1){|i|
@limits << (limits[i] || INFINITY)
}
@content = {}
end
attr_reader :dimensions
attr_reader :limits
=begin rdoc
=end
def checkkeys(keys)
raise ArgumentError, "Additional key values for %i-dimensional Array" % @dimensions if keys.size > @dimensions
raise ArgumentError, "Missing key values for %i-dimensional Array" % @dimensions if keys.size != @dimensions
raise ArgumentError, "No keys given" if keys.size == 0
keys.each_with_index{|key,i|
raise ArgumentError, "Exceeded limit for %i dimension" % (i+1) if key > @limits[i]
raise ArgumentError, "Only positive numbers allowed" if key < 1
}
end
def[]=(*keys)
data = keys.pop
checkkeys(keys)
@content[keys] = data
end
def[](*keys)
checkkeys(keys)
@content[keys]
end
end
这可以用作:
arr = MArray.new()
arr[1,1] = 3
arr[2,2] = 3
如果您需要一个预定义的 2x2 矩阵,您可以将其用作:
arr = MArray.new(2,2,2)
arr[1,1] = 3
arr[2,2] = 3
#~ arr[3,2] = 3 #Exceeded limit for 1 dimension (ArgumentError)
我可以想象如何在二维数组中处理诸如<< 或each 之类的命令,而不是在多维数组中。
【讨论】:
记住数组是 ruby 中的对象可能会有所帮助,并且对象不是(默认情况下)通过命名它们或命名对象引用来创建的。下面是一个创建 3 维数组并将其转储到屏幕进行验证的例程:
def Create3DimensionArray(x, y, z, 默认) n = 0 # 仅验证码 ar = Array.new(x) 对于我在 0...x ar[i] = Array.new(y) 对于 j 在 0...y ar[i][j] = Array.new(z, 默认值) for k in 0...z # 仅验证码 ar[i][j][k] = n # 仅验证码 n += 1 # 仅验证码 end # 仅验证码 结尾 结尾 返回 结尾 # 创建样本并验证 ar = Create3DimensionArray(3, 7, 10, 0) 对于 x 在 ar 放“||” 对于 x 中的 y 放“|” 对于 z in y printf "%d", z 结尾 结尾 结束【讨论】:
for x in 0...ar.length for y in 0...ar[x].length for z in 0...ar[x][ y].length printf "%3d", ar[x][y][z] end puts "|" end puts "--" end
这是一个 ruby 中的 3D 数组类的实现,在这种情况下,默认值为 0
class Array3
def initialize
@store = [[[]]]
end
def [](a,b,c)
if @store[a]==nil ||
@store[a][b]==nil ||
@store[a][b][c]==nil
return 0
else
return @store[a][b][c]
end
end
def []=(a,b,c,x)
@store[a] = [[]] if @store[a]==nil
@store[a][b] = [] if @store[a][b]==nil
@store[a][b][c] = x
end
end
array = Array3.new
array[1,2,3] = 4
puts array[1,2,3] # => 4
puts array[1,1,1] # => 0
【讨论】: