我正在为二维数组编写基本函数。有两种方法可以编写“set”功能。第一个是制作矩阵的副本然后修改它:
let copy_matrix (m: 'a array array): 'a array array =
let l = Array.length m in
if l = 0 then m else
let result = Array.make l m.(0) in
for i = 0 to l - 1 do
result.(i) <- Array.copy m.(i)
done;
result
let set_copy (m: 'a array array) (r: int) (c: int) (v: 'a): 'a array array =
let m' = copy_matrix m in
m'.(r).(c) <- v;
m'
第二个只是直接在矩阵上修改:
let set (m: 'a array array) (r: int) (c:int) (v: 'a) : unit =
m.(r).(c) <- v
我认为如果是在Java中,第二个功能显然比第一个功能更快更经济。然而,有人(我忘了)告诉我1)OCaml的内存管理非常聪明,set_copy
成本不高,2)有一些原因(我忘了)最好使用{ {1}}比set_copy
。
有人能告诉我这是否属实?
答案 0 :(得分:5)
如果你需要持久化数组(你需要保留所有版本以用于回溯目的等),复制版本当然要好得多,但它会很慢。我们在this StackOverflow post中讨论了持久化数组结构,如果你想要持久化,你应该考虑使用它们而不是普通数组。使用持久数组的持久数组处理矩阵可能会运行得相当好。当然,您也可以使用Map类型为(int * int)
的键作为起点(但访问费用是不可忽略的)。
如果你不需要持久化(你永远不需要保持“旧”数组),避免复制和保持标准数据类型会更好。
此外,您可以将matrix_copy
实现为
let matrix_copy m = Array.map Array.copy m
答案 1 :(得分:3)
我不认为每次想要更改一个值时都有任何内存管理魔法可以覆盖复制整个数组。
使用不可变数据有很好的理由,这些数据适用于数组以及其他所有数据。但除非阵列很小,否则您显示的复制代码会产生相当大的代价。
还有其他方法可以表示不需要那么多复制的数组(例如,差异列表或树)。但当然他们有自己的问题。