我想知道在scala中保存数组初始状态的最佳方法是什么,这样我可以在操作工作副本后重置初始值。我想做这样的事情
val initialValue = Array(Array(1,2,3),Array(4,5,6))
val workingCopy = initialValue.clone
问题在于,当我更改workingCopy的值时,我也会更改initialValue的值。
我也试过
val workingCopy = Array.fill(2,3)(0)
Array.copy(initialValue,0,workingCopy,2)
但我得到的结果相同。
即使我在定义数组时使用var
而不是val
,这也成立。我认为这种浅层复制行为可能是由嵌套数组结构引起的,但我不确定如何处理它。
答案 0 :(得分:1)
正如Angelo所指出的,您通常希望使用不可变数据结构来避免这样的问题。但是,如果你真的需要采取可变的方式,例如出于性能原因(尽管不可变集合的“修改”,例如Vector
,并不像您想象的那么昂贵),那么您需要对嵌套数组执行深层复制和内容。实施取决于您。
如果它真的只是一个Array[Array[Int]]
,就足以做到这样的事情:
val initialValue = Array(Array(1,2,3), Array(4,5,6))
val workingCopy = initialValue.map(_.clone)
使用引用类型而不是简单Int
的更一般的示例:
scala> class Cell(var x: String) { def copy = new Cell(x); override def toString = x }
defined class Cell
scala> val initialValue = Array(Array(new Cell("foo")))
initialValue: Array[Array[Cell]] = Array(Array(foo))
scala> val workingCopy = initialValue.map(_.map(_.copy))
workingCopy: Array[Array[Cell]] = Array(Array(foo))
scala> initialValue(0)(0).x = "bar"
initialValue(0)(0).x: String = bar
scala> initialValue
res0: Array[Array[Cell]] = Array(Array(bar))
scala> workingCopy
res1: Array[Array[Cell]] = Array(Array(foo))
而不是initialValue.map(_.map(_.copy))
,当然还有其他方法可以做同样的事情(例如,嵌套的for
表达式将对象复制为副作用。)
答案 1 :(得分:0)
var
vs val
实际上只是确定引用是否是不可变的,它对数据结构的内容没有影响。如果要转换为不可变数据结构,例如List
,那么副本将不再需要作为"修改"的操作。这种结构的内容创造了一个新的参考,使原始结构不受影响。
例如:
val initialValue = List(List(1,2,3),List(4,5,6))
val sumInnerLists = initialValue.map(l => l.foldLeft(0)(_ + _))
println(sumInnerLists) // List(6, 15)
println(initialValue) // List(List(1,2,3),List(4,5,6))