Ruby中map!未改变关联变量,如何实现变量与数组元素同步更新?
如何让变量和数组中的元素同步变化?
这个问题其实戳中了Ruby里不可变对象和变量引用的核心逻辑,咱们先把你遇到的现象拆解清楚,再给你可行的解决方案~
为什么当前操作无法同步?
首先要明确:Ruby里的Integer(整数)是不可变对象——也就是说,你没法修改一个已存在的整数对象本身的值,所有看起来像是“修改”的操作,其实都是生成了一个新的整数对象,然后让变量指向这个新对象。
第一个例子:修改x后y不变
x = 1 # => 1 y = [x] # => [1] x = x+1 # => 2 x # => 2 y # => [1]
这里的x = x+1并不是把原来的1改成2,而是创建了一个新的整数对象2,然后让变量x指向这个新对象。而数组y里保存的还是原来那个1的引用,所以y自然不会跟着变。
第二个例子:修改y后x不变
x = 1 # => 1 y = [x] # => [1] y.map!{|a| a+1} # => [2] y # => [2] x # => 1
map!里的a+1同样是生成了新的整数对象2,然后把数组y里的元素替换成这个新对象。但变量x依然指向原来的1,所以x的值不会改变。
实现同步变化的方法:用可变对象包裹值
要让变量和数组元素同步变化,关键是使用可变对象——也就是可以修改内部状态的对象,这样所有指向这个对象的引用(不管是变量还是数组元素),都会共享它的状态变化。
方案1:自定义一个简单的包装类
这是最清晰、最通用的方式:
class ValueWrapper attr_accessor :value # 提供读写value的方法 def initialize(initial_value) @value = initial_value end end # 测试同步效果 x = ValueWrapper.new(1) y = [x] # 修改x的value x.value += 1 x.value # => 2 y.first.value # => 2 # 数组里的元素跟着变了! # 修改数组里元素的value y.first.value += 1 x.value # => 3 # 变量x也同步更新了!
方案2:用数组/哈希当临时容器
如果不想写自定义类,也可以用Ruby自带的可变容器(比如数组)来包裹值:
x = [1] # 用数组包裹整数 y = [x] # 修改x的内部值 x[0] += 1 x # => [2] y.first # => [2] # 修改数组里元素的内部值 y.first[0] += 1 x # => [3]
简单来说,只要让变量和数组元素指向同一个可变对象,修改这个对象的内部状态时,所有引用都会同步看到变化~
内容的提问来源于stack exchange,提问作者preferred_anon
相关产品推荐
相关产品推荐

