2008-03-18

Trick: Ruby的二维数组

关键字: ruby, array, trick

 缘起:

 昨天跟一个学习ruby的网友聊天,刚好二维数组,对方抛给我一个问题,是这样的:

 创建一个含有3个元素的二维数组,并填充所有数组元素为'0'

arr = Array.new(3, Array.new(3,0))
 然后改写一个二维数组中一个元素的数值
arr[1][1] = 1
 打印数组
p arr

 得到的结果是

[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
 也就是说二维数组中每个sub array都被赋值


 但是如果采用数组字面量方式创建爱昵一个二维数组

arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
 重复上面的步骤,改写一个元素的值
arr[1][1] = 1
p arr
 得到的答案是
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]

 

 第二种方法得到的值是我想要的,也是符合我心里预期的.但是我确并不能理解第一种方式问题在哪里.

 用ruby的equals测试

>> Array.new(3, Array.new(3,0)) == [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
=> true
>> Array.new(3, Array.new(3,0)) === [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
=> true

 结果也表示两种方式返回的对象值相同

 

Shanghaionrails上的sishen帮助我解释了这个问题,感谢sishen同学,代码如下

Array.new(3, Array.new(3,0)).each{|i|p i.object_id}
-616182288
-616182288
-616182288

[[0, 0, 0], [0, 0, 0], [0, 0, 0]].each{|i|p i.object_id}
-616198918
-616198928
-616198938
即按照第一种方式创建的二维数组,内部sub array其实是指向内存中的同一个对象.一般用数组,总是习惯上直接   用字面常量方式赋值来创建,一直没有注意到这个问题,以后处理二维/n维数组时要小心啦.

 

评论
simohayha 2008-03-19
嘿嘿,这个ruby way里面都有讲的说。

http://simohayha.javaeye.com/blog/151085
Quake Wang 2008-03-19
在ruby的Array文档上有说明的,用上述的构建方法,其实是一个object copy,你可以用block来解决这个问题:

arr = Array.new(3){Array.new(3,0)}
yangtao309 2008-03-19
不错 记下 也测试了这个问题!
dennis_zane 2008-03-19
是个小陷阱,不小心还真容易中招
发表评论

您还没有登录,请登录后发表评论

lgn21st
搜索本博客
存档
最新评论