下面有两种方法:两者是相同的,只是一个clone
输入,而另一个不同。
方法1
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]
方法2
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
方法来避免这种突变?
答案 0 :(得分:10)
[...]会改变原始输入,即使我对原始数组的副本执行所有操作。
您不对副本执行操作。做的时候
new = array
它不会导致复制操作。相反,分配使new
只是引用了array
所引用的同一对象。因此,调用new.reject!
或array.reject!
都没有关系,因为reject!
被发送到同一接收者。
为什么需要一种显式的
.clone
方法来避免这种突变?
因为clone
执行了您为=
进行的复制操作。从文档中:
产生 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