ここで問題を見つけるのは私の能力の不足だけかもしれませんが、Rubyで多次元配列を作成する方法については何も見つかりません。
誰かがそれを行う方法の例を教えてもらえますか?
ブロックをArray.new
に渡すことができます
Array.new(n) {Array.new(n,default_value)}
ブロックを返す値は、最初の配列の各インデックスの値になります。
そう..
Array.new(2) {Array.new(2,5)} #=> [[5,5],[5,5]]
array[x][y]
を使用してこの配列にアクセスできます
2番目の配列のインスタンス化でも、ブロックをデフォルト値として渡すことができます。そう
Array.new(2) { Array.new(3) { |index| index ** 2} } #=> [[0, 1, 4], [0, 1, 4]]
単なる説明:
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)を初期化するには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]
配列aを変更し、配列aの要素を出力するため、0.0ではなく1.0を出力します。
PHPスタイルの多次元配列をRubyで最近再現しなければなりませんでした。
# 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
実際、これは上記のブロックメソッドよりもはるかに高速です。
arr = Array.new(n, Array.new(n, Array.new(n,0.0)))
arr[0][1][2] += 1
使用にはXKeys Gemも使用できます。
require 'xkeys'
regular = [].extend XKeys::Auto
regular[1,2,3] = 4
# [nil, [nil, nil, [nil, nil, nil, 4]]]
regular[3,2,1, :else=>0] # 0
# Note: regular[1,2] is a slice
# Use regular[1,2,{}] to access regular[1][2]
sparse = {}.extend XKeys::Hash
sparse[1,2,3] = 4
# {1=>{2=>{3=>4}}}
path=[1,2,3]
sparse[*path,{}] # 4
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
配列はRubyのオブジェクトであり、オブジェクトは(デフォルトでは)名前を付けたりオブジェクト参照に名前を付けたりするだけでは作成されないことを覚えておくと役立ちます。以下は、3次元配列を作成し、確認のために画面にダンプするためのルーチンです。
def Create3DimensionArray(x、y、z、default) n = 0#検証コードのみ ar = Array.new(x) for i in 0 ... x ar [i] = Array.new(y) in j in 0 ... y ar [i] [j] = Array.new( z、デフォルト) for k in 0 ... z#検証コードのみ ar [i] [j] [k] = n#検証コードのみ n + = 1#検証コードのみ end#検証コードのみ end end return ar end #サンプルを作成し、検証する ar = Create3DimensionArray(3、7、10、0) for x in ar puts "||" [y] for x puts "|" z for y printf "%d"、z end end 終わり
おそらく、ハッシュを使用して多次元配列をシミュレートできます。ハッシュキーは、任意の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)
多次元配列ではなく、2次元配列で<<
やeach
などのコマンドを処理する方法を想像できました。