在OCaml中转置列表列表

时间:2015-04-13 14:08:10

标签: ocaml

let rec transpose list = match list with
| []             -> []
| []   :: xss    -> transpose xss
| (x::xs) :: xss ->
    (x :: List.map List.hd xss) :: transpose (xs :: List.map List.tl xss)

我在这个网站上找到了这个代码并且它转换了一个列表列表,或者在我的情况下转换了从n×m到m×n的矩阵。唯一的问题是我不知道它是如何工作的。任何人都可以一步一步地逐一解释。

1 个答案:

答案 0 :(得分:2)

您还应提供代码链接,上下文,或查看该问题以获得解释。

无论哪种方式,我怀疑其他新的OCaml程序员会在这个问题上寻找答案。

- 经过快速Google搜索后,我相信这是您发现代码的question

let rec transpose list = match list with

  • 创建一个名为transpose的函数,使其递归(rec),因为我们将调用函数本身。它将采用名为list的输入参数,其中类型由OCaml的类型系统确定。

  • 将输入参数list与以下情况匹配。也就是说,当函数找到与这些情况匹配的模式时,它将执行该特定代码行。如果编写的代码不涵盖所有情况,OCaml将通知并非所有情况都是详尽无遗的,并且如果遇到它未涵盖的情况,将导致match_failure

第一种情况:

| [] -> []

  • 如果我们点击一​​个空列表,则返回一个空列表。这将结束递归,因为空列表被附加到最终结果并返回。空列表是一个基本案例,我们遇到一个里面没有任何内容的列表,或者它已经递归,直到没有任何内容。 (空列表的转置是......和空列表)

| [] :: xss -> transpose xss

  • 这是列表中仍有项目的情况。由于它是列表列表,因此我们传入的列表中的每个元素都是另一个列表。即,[[1;2];[3;4]],所以这个函数处理我们有[[];[1;2];[5;6]]的情况,它将跳过空的内部列表,然后在另一个[[1;2];[5;6]]上调用转置,因为我们没有xss。需要转置一个空列表。请注意,| (x::xs) :: xss -> (x :: List.map List.hd xss) :: transpose (xs :: List.map List.tl xss)是列表的其余部分(因此列表列表),而不仅仅是下一个元素(它只是一个列表)。

match

  • 这是我们传入任何长度列表的常规列表时将匹配的第一种情况> 1,OCaml能够匹配并且还能够打开"展开"通过将每个元素分解以适应模式,我们可以立即计算这些元素而不使用嵌套的(x::xs)语句。在这种情况下,我们将列表列表拆分为xss列表(第一个元素)和剩余列表列表x::xss。我们也可以将其作为[[1;2];[3;4]]来完成,但x将是一个我们需要再次分解为单个元素的列表。 例如,在xss中,(x :: xs)将为[1; 2]而(x :: List.map List.hd xss)将为[[3; 4]]

  • List.hd将获取第一个列表中的第一个元素,在给定示例中,x将为1.并将该值应用于{{1}中每个项目的xss } list,(List.Map将函数应用于列表中的每个值)。

  • 这是一个有点复杂的地方。您如何看待它:当您致电List.hd [1;2;3]时,它将返回1,因为它是头部。因此,当我们执行3 :: List.map List.hd [[1;2]]时,它将返回int list = [3; 1]。我们得到3 :: List.map List.hd [[1;2];[4;5]]我们得到[3;1;4]因为我们得到了较大列表中每个列表的头部,并在结果列表的前面附加3。
  • 如果您改为List.map List.tl [[1;2];[4;5]],则返回类型将为[2; 5],因为List.map将List.tl函数应用于每个列表。您可以使用List.map以快速简便的方式为列表中的每个项目应用乘法函数(或任何复杂的函数)。

剩下的transpose (xs :: List.map List.tl xss)只调用转置到列表中的其余项目,这是xss(所有列表)的尾值,附加了xs中的元素。如果您觉得需要更具体地掌握它,请在纸上试一试。