下面有两种方法;除了一个 clone
是输入而另一个不是,两者是相同的。
方法一
arr = [1,2,3,1,2,3]
def remove_smallest(array)
new = array
new.reject! {|i| i <= new.min}
new
end
remove_smallest(arr)
#=> [2,3,2,3]
arr
#=> [2,3,2,3]
方法二
arr = [1,2,3,1,2,3]
def remove_smallest(array)
new = array.clone
new.reject! {|i| i <= new.min}
new
end
remove_smallest(arr)
#=> [2,3,2,3]
arr
#=> [1,2,3,1,2,3]
如果没有 clone
,即使我对原始数组的副本执行所有操作,该方法也会改变原始输入。
为什么需要显式clone
方法来避免这种突变?
最佳答案
[...] will mutate the original input even if I perform all operations on a copy of the original array.
您不对副本执行操作。做的时候
new = array
它不会导致复制操作。相反,作业使 new
简单地引用同一个对象 array
指的是。因此,调用 new.reject!
并不重要或 array.reject!
因为reject!
被发送到同一个接收者。
Why is an explicit
.clone
method needed to avoid this mutation?
因为 clone
执行您为 =
假定的复制操作.来自文档:
Produces a shallow copy of obj [...]
另一种避免这种突变的方法是改用非突变方法:
def remove_smallest(array)
array.reject {|i| i <= array.min }
end
或者——为了避免重新计算每一步的最小值:
def remove_smallest(array)
min = array.min
array.reject {|i| i <= min }
end
您还可以使用 ==
而不是 <=
因为min
已经是最小的可能值。
或者,有 Array#-
:
def remove_smallest(array)
array - [array.min]
end
关于ruby - 为什么 ruby 在我不要求时改变我的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55252912/