Ruby 多维数组

发布于 2024-11-28 15:55:34 字数 87 浏览 4 评论 0原文

也许只是我缺乏在这里找到东西的能力,这就是问题所在,但我找不到任何关于如何在 Ruby 中创建多维数组的信息。

有人可以给我一个如何做的例子吗?

Maybe it's just my lack of abilities to find stuff here that is the problem, but I can't find anything about how to create multidimensional arrays in Ruby.

Could someone please give me an example on how to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

镜花水月 2024-12-05 15:55:35

也许您可以用哈希来模拟多维数组。哈希键可以是任何 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 在二维数组中,但在多维数组中则不然。

Perhaps you can simulate your multidimensional Array with a Hash. The Hash-key can by any Ruby object, so you could also take an array.

Example:

marray = {}
p marray[[1,2]]   #-> nil
marray[[1,2]] = :a
p marray[[1,2]]   #-> :a

Based on this idea you could define a new class.

Just a quick scenario:

=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

This can be used as:

arr = MArray.new()
arr[1,1] = 3
arr[2,2] = 3

If you need a predefined matrix 2x2 you can use it as:

arr = MArray.new(2,2,2)
arr[1,1] = 3
arr[2,2] = 3
#~ arr[3,2] = 3  #Exceeded limit for 1 dimension (ArgumentError)

I could imagine how to handle commands like << or each in a two-dimensional array, but not in multidimensional ones.

怪我太投入 2024-12-05 15:55:35

记住数组是 ruby​​ 中的一个对象,并且对象不是(默认情况下)简单地通过命名或命名对象引用来创建的,这可能会有所帮助。以下是创建 3 维数组并将其转储到屏幕进行验证的例程:

def Create3DimensionArray(x, y, z, default)
    n = 0                       # verification code only
    ar = Array.new(x)
    for i in 0...x
        ar[i] = Array.new(y)
        for j in 0...y
            ar[i][j] = Array.new(z, default)
            for k in 0...z      # verification code only
                ar[i][j][k] = n # verification code only
                n += 1          # verification code only
            end                 # verification code only
        end
    end
    return ar
end

# Create sample and verify
ar = Create3DimensionArray(3, 7, 10, 0)

for x in ar
    puts "||"
    for y in x
        puts "|"
        for z in y
            printf "%d ", z
        end
    end
end

It might help to remember that the array is an object in ruby, and objects are not (by default) created simply by naming them or naming a the object reference. Here is a routine for creating a 3 dimension array and dumping it to the screen for verification:

def Create3DimensionArray(x, y, z, default)
    n = 0                       # verification code only
    ar = Array.new(x)
    for i in 0...x
        ar[i] = Array.new(y)
        for j in 0...y
            ar[i][j] = Array.new(z, default)
            for k in 0...z      # verification code only
                ar[i][j][k] = n # verification code only
                n += 1          # verification code only
            end                 # verification code only
        end
    end
    return ar
end

# Create sample and verify
ar = Create3DimensionArray(3, 7, 10, 0)

for x in ar
    puts "||"
    for y in x
        puts "|"
        for z in y
            printf "%d ", z
        end
    end
end
薄荷→糖丶微凉 2024-12-05 15:55:35

这是 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

Here is an implementation of a 3D array class in ruby, in this case the default value is 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
知你几分 2024-12-05 15:55:34

严格来说,在 Ruby 中创建多维数组是不可能的。但是可以将一个数组放入另一个数组中,这与多维数组几乎相同。

这是在 Ruby 中创建二维数组的方法:

a = [[1,2,3], [4,5,6], [7,8,9]]


As stated in the comments, you could also use NArray which is a Ruby numerical array library:

require 'narray'
b = NArray[ [1,2,3], [4,5,6], [7,8,9] ]

使用a[i][j] 访问数组的元素。基本上,a[i] 返回存储在 ai 位置的“子数组”,因此 a[i][j] 从存储在位置 i 的数组中返回元素编号 j

Strictly speaking it is not possible to create multi dimensional arrays in Ruby. But it is possible to put an array in another array, which is almost the same as a multi dimensional array.

This is how you could create a 2D array in Ruby:

a = [[1,2,3], [4,5,6], [7,8,9]]


As stated in the comments, you could also use NArray which is a Ruby numerical array library:

require 'narray'
b = NArray[ [1,2,3], [4,5,6], [7,8,9] ]

Use a[i][j] to access the elements of the array. Basically a[i] returns the 'sub array' stored on position i of a and thus a[i][j] returns element number j from the array that is stored on position i.

忆沫 2024-12-05 15:55:34

您可以将一个块传递给 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.new(2) { Array.new(3) { |index| index ** 2} } #=> [[0, 1, 4], [0, 1, 4]]

you can pass a block to Array.new

Array.new(n) {Array.new(n,default_value)}

the value that returns the block will be the value of each index of the first array,

so..

Array.new(2) {Array.new(2,5)} #=> [[5,5],[5,5]]

and you can access this array using array[x][y]

also for second Array instantiation, you can pass a block as default value too. so

Array.new(2) { Array.new(3) { |index| index ** 2} } #=> [[0, 1, 4], [0, 1, 4]]
墨落画卷 2024-12-05 15:55:34

只是澄清一下:

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]]

Just a clarification:

arr = Array.new(2) {Array.new(2,5)} #=> [[5,5],[5,5]]

is not at all the same as:

arr = Array.new(2, Array.new(2, 5))

in the later case, try:

arr[0][0] = 99

and this is what you got:

[[99,5], [99,5]]
金橙橙 2024-12-05 15:55:34

有两种方法可以初始化多数组(大小为 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"

There are two ways to initialize multi array (size of 2).
All the another answers show examples with a default value.

Declare each of sub-array (you can do it in a runtime):

multi = []
multi[0] = []
multi[1] = []

or declare size of a parent array when initializing:

multi = Array.new(2) { Array.new }

Usage example:

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"

So you can wrap the first way and use it like this:

@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"
弄潮 2024-12-05 15:55:34

上面给出的方法不起作用。

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 的元素。

The method given above don't works.

n = 10
arr = Array.new(n, Array.new(n, Array.new(n,0.0))) 
arr[0][1][2] += 1
puts arr[0][2][2]

is equivalent to

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]

and will print 1.0, not 0.0, because we are modifiyng array a and printing the element of array a.

凉世弥音 2024-12-05 15:55:34

实际上这比上面给出的 block 方法要快得多:

arr = Array.new(n, Array.new(n, Array.new(n,0.0))) 

arr[0][1][2] += 1

Actually this is much quicker than the block method given above:

arr = Array.new(n, Array.new(n, Array.new(n,0.0))) 

arr[0][1][2] += 1
抱着落日 2024-12-05 15:55:34

最近我不得不在 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

I had to reproduce PHP-style multidimensional array in Ruby recently. Here is what I did:

# 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文