我需要检查数组是否在OCaml中正确排序。
因此,我正在考虑将字符2分组2,然后进行折叠操作,我将其进行比较。
但是,我不知道如何将它们分组。
在Scala中,它看起来像这样:
val k = Array(1, 2, 3, 4)
k.zip(k.tail)
知道在OCaml中看起来会怎样?
答案 0 :(得分:3)
使用Array.init
函数创建一个新数组并用它们填充它,例如..
let zip xs ys = Array.init (Array.length xs) (fun i -> x.(i),y.(i))
但是,我不推荐这种方法。如果您可以使用递归函数轻松表达算法,则没有理由创建中间数据结构。
如果您需要将数组xs
与数组ys
进行比较,那么您只需执行xs = ys
。
看起来,您还希望不创建两个数组的zip,但是从数组中提取连续元素对,这里可以使用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)
样式装饰/进程/ undecorate在懒惰序列中运行良好,在编译器中具有良好的森林砍伐能力。例如在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
将检查它们是否全部排序。
答案 1 :(得分:2)
这将使数组成为一对相邻元素的列表:
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认为创建这个中间数据结构可能不值得。您可以使用几乎相同的函数来比较相邻元素,并累积一个布尔值,表明它们是否都是正确的顺序。