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的矩阵。唯一的问题是我不知道它是如何工作的。任何人都可以一步一步地逐一解释。
答案 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中的元素。如果您觉得需要更具体地掌握它,请在纸上试一试。