提问人:kranz 提问时间:11/8/2013 更新时间:11/8/2013 访问量:158
ruby 如何与数组数组一起工作 [已关闭]
How does ruby works with array of arrays [closed]
问:
我正面临着一些我不完全理解的事情。
我有一个数组,其元素是数组。
所以我有两个嵌套的循环,在内部循环中我填充我的内部数组 然后在外部循环中,我用内部数组填充外部数组。
arr=[]
mat=[]
for m in (0..1)
for k in (0..1)
arr[k]=rand.to_s
end
mat[m]=arr
end
最后,我的矩阵被两个数组填满;每个数组都包含在上次迭代中计算的值。 如果我希望矩阵中的第一个元素包含第一个计算数组,我必须在每个循环中重新初始化 arr 对象。 因此,在 arr 对象被“清理”之前,赋值似乎是通过引用进行的。如果我添加
mat[m]=arr
arr=[]
一切按预期工作:mat[0] 将包含第一个循环中计算的数组,mat[1] 将包含第二个循环中计算的数组。
这是设计使然还是不希望的副作用? 只有当我将数组指定为数组元素时,才会发生这种情况。如果 if 在循环中用简单的字符串变量填充数组,则一切都按预期进行。
我知道避免重用对象是很好的编程实践,但这种行为无论如何都很奇怪。
答:
4赞
Denis de Bernardy
11/8/2013
#1
你的问题是你的 arr 变量的内容在每次迭代时都会被覆盖:覆盖已经存在的任何内容。arr 变量需要是块的本地变量:arr[k]
mat = []
2.times do # avoid for... use iterators instead
row = []
2.times do
row << rand.to_s
end
mat << row
end
评论
0赞
Denis de Bernardy
11/8/2013
@Niel:实际上,这或多或少是我的意思。不过,我的非母语英语可能会妨碍我。;-)我以一种希望更好的方式重新表述了它。
0赞
Neil Slater
11/8/2013
是的,我认为现在我已经足够好了,因为我删除了我的评论并 +1-ed
0赞
kranz
11/8/2013
@Denis:谢谢,我已经发现这就是它的工作方式。问题是它是否正确。我希望每次我做 mat << row 时,都会添加一个 row 副本作为 mat 的新元素。仅当在每次迭代时重新初始化行时,才会发生这种情况。否则,mat 会添加指向行的指针,而不是 is content。我错了吗?
0赞
kranz
11/8/2013
@Denis:也许现在我明白了。这是一个可变范围的问题。在两个循环之外声明行是错误的。
0赞
Denis de Bernardy
11/8/2013
@kranz:是的,你的具体问题是范围界定。关于在 or 中添加的内容,您总是在添加指向对象的指针。如果没有适当的范围,您最终会两次引用同一行,您可以通过漂亮的打印来运行它来查看这一点。mat =
mat[m] =
0赞
Conkerchen
11/8/2013
#2
我喜欢使用哈希而不是多维数组的方法。
这个怎么样:
def create_matrix x, y, content = nil, &block
rows = (0...x).to_a
cols = (0...y).to_a
indices = rows.product cols
matrix = {}
indices.each { |index| matrix[index] = ( block_given? ? yield( index ) : content ) }
matrix
end
然后执行:
matrix = create_matrix( 2, 2 ) { rand.to_s }
你会得到一个哈希值,你可以像这样访问它:
matrix[[0, 1]] #note the double brackets
0赞
hirolau
11/8/2013
#3
另一种方法:
(1..4).map{rand}.each_slice(2).to_a
评论