我需要检查一个数组是否在OCaml中正确排序。
因此,我想分组字符2乘2,然后做一个折叠操作,我比较他们。
不过,我不知道怎么把他们分组。
在Scala中,它看起来如下所示:
val k = Array(1, 2, 3, 4)
k.zip(k.tail)
你知道在OCaml里会是什么样子吗?
发布于 2016-10-27 18:49:05
使用Array.init
函数,创建一个新数组并将其填充成对,例如.
let zip xs ys = Array.init (Array.length xs) (fun i -> x.(i),y.(i))
但是,我不推荐这种方法。如果您可以轻松地用递归函数表达算法,就没有理由创建中间数据结构。
如果需要比较数组xs
和数组ys
,那么只需做xs = ys
。
看起来,您也不希望创建一个由两个数组组成的压缩,而是从数组中提取成对的连续元素,这里是如何使用Array.init
实现的。
let zip_with_tail xs = match Array.length xs with
| 0 | 1 -> [| |]
| n -> Array.init (n-1) (fun i -> xs.(i),xs.(i+1))
将其与不使用中间数据结构的is_sorted
函数进行比较:
let is_sorted xs = let rec ordered i = i = 0 || xs.(i-1) <= xs.(i) && ordered (i-1) in match Array.length xs with | 0 | 1 -> true | n -> ordered (n-1)
样式修饰/处理/取消装饰可以很好地处理懒散序列,在擅长去林的编译器中工作。比如在Haskell。或者用已经很慢的语言,没有必要去费心。我不确定Scala,他们的数组是否懒惰。无论如何,OCaml数组是一个具体的数据结构,OCaml编译器不会优化它(也不应该--数组的语义不允许这样做)。然而,这种编程风格仍然适用于OCaml。您可以使用Core
库,它提供了一个名为Sequence
的惰性容器。您可以轻松地用同样的方式定义zip_with_tail
,就像在Scala中那样:
let zip_with_tail xs = Sequence.(zip xs (drop xs 1))
下面是一个示例:
# let xs = Sequence.of_list [1;2;3;4;5;6];;
val xs : int Core_kernel.Std.Sequence.t = {1, 2, 3, 4, 5, 6}
# zip_with_tail xs;;
- : (int * int) Core_kernel.Std.Sequence.t =
{(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)}
因此,您可以很好地定义is_sorted
:
let is_sorted xs = zip_with_tail xs |>
Sequence.for_all ~f:(fun (x,y) -> x <= y)
这里,zip_with_tail xs
不会创建一个中间数组,它实际上具有O(1)复杂性。在引擎盖下面,它将返回一个函数,它将生成元素。Sequence.for_all
将检查它们是否都已排序。
发布于 2016-10-27 19:04:12
这将使数组成为一对相邻元素的列表:
let a2pairs a =
let mkpr x (prevo, prs) =
match prevo with
| None -> (Some x, [])
| Some y -> (Some x, (x, y) :: prs)
in
snd (Array.fold_right mkpr a (None, []))
它的工作方式如下:
# a2pairs [| 1;2;3;4 |];;
- : (int * int) list = [(1, 2); (2, 3); (3, 4)]
但我同意@ivg的观点,即创建这种中间数据结构可能不值得。您可以使用几乎相同的函数来比较相邻的元素,并积累一个布尔值,以说明它们是否都是正确的。
https://stackoverflow.com/questions/40291948
复制相似问题