Ruby数组意外批量赋值问题:如何仅修改首个元素值?
解决Ruby多层嵌套数组批量赋值的问题
嘿,这个问题我之前也踩过一模一样的坑!根源其实出在Ruby里Array.new的参数使用方式上——当你用Array.new(n, obj)这种形式创建数组时,数组里的n个元素全都是同一个对象的引用,并不是各自独立的新对象。
你看,你创建@master = Array.new(4, Array.new(2, Array.new()))的时候:
- 外层的4个元素,指向的是同一个
[[], []]子数组 - 而这个子数组里的两个元素,又指向同一个空数组
所以当你执行@master[0][0] = "x"时,你修改的是那个被所有外层元素共享的子数组的第一个位置,自然所有外层数组的对应位置都会跟着变成"x"。
解决方案:用块形式创建独立的嵌套数组
最优雅的方式是从创建数组的时候就避免共享引用,改用块版本的Array.new——块会为每个元素单独执行一次,生成全新的对象:
# 用块创建每层独立的数组 @master = Array.new(4) { Array.new(2) { Array.new() } }
现在再测试赋值:
@master[0][0] = "x" puts @master.inspect # 输出:[["x", []], [[], []], [[], []], [[], []]]
这样每层数组的元素都是独立的对象,修改其中一个只会影响对应的位置,不会批量改变其他元素。
备选方案:修改已创建的数组
如果已经创建了原来的数组,不想重新创建的话,可以先把第一个外层元素替换成独立的子数组,再赋值:
# 先替换第一个外层元素为全新的子数组 @master[0] = [Array.new(), Array.new()] # 再赋值 @master[0][0] = "x"
不过这种方法不如从一开始就用块创建数组来得高效和优雅,更推荐第一种方案从根源解决问题。
内容的提问来源于stack exchange,提问作者userFriendly
相关产品推荐
相关产品推荐

