我正在学习f#,没有任何先前的函数式编程背景 - 开始取得进展但却陷入了困境。任何人都可以帮助我理解99 f#问题9的解决方案 - 可以在这里找到:[http://fssnip.net/an] [1]
基本上我不明白模式匹配在提供的解决方案中是如何工作的。一开始什么是xss?欢呼任何帮助!
问题9:将列表元素的连续重复包装到子列表中。 如果列表包含重复的元素,则应将它们放在单独的子列表中。
示例:
打包['a'; '一个'; '一个'; '一个'; 'B'; 'C'; 'C'; '一个'; '一个'; 'D'; 'E'; 'E'; 'E';的 'e']
val it:char list list = [['一个'; '一个'; '一个'; '一个']; [ 'B']; ['C'; 'C']; ['一个'; '一个']; [ 'D']; [ 'E'; 'E'; 'E';的 'e']]
示例解决方案;
let pack xs =
let collect x = function
| (y::xs)::xss when x = y -> (x::y::xs)::xss
| xss -> [x]::xss
List.foldBack collect xs []
答案 0 :(得分:1)
(y::xs)::xss
匹配(非空)列表列表,y
和xs
是第一个子列表的头部和尾部,xss
是列表的尾部外部清单。在第二种情况下,xss
匹配整个列表(空或不)。
foldBack
(('T -> 'State -> 'State) -> 'T list -> 'State -> 'State
)通过列表线程化一个累加器参数,从后到前。
collect
是"累积"函数,基本上读取:如果状态(最初是一个空列表)包含至少一个子列表,也是非空的,并且当前元素(x
)匹配子列表的头部({{1} }),将y
添加到子列表,否则将新的子列表添加到仅由x
组成的状态(xss
)。每个子列表都是一组相等的相邻元素。
答案 1 :(得分:1)
要理解这一点,首先要了解如何在F#中表示列表。 F#列表是:
[]
或head::tail
因此,如果您编写[ 1; 2; 3 ]
,您实际上正在构建一个包含1的列表,后面跟一个包含2的列表,(等等)后跟一个空列表。表达式编译为:
1::(2::(3::[]))
你可以省略括号并只写1::2::3::[]
。
模式匹配使用完全相同的语法,但方向相反。您不是在构建列表,而是分解它们。因此,如果您使用模式x::xs
,则表示您想要获取第一个元素并将其分配给变量x
,其余列表应该被赋值给变量xs
。
模式(x::xs)::xss
有点棘手,因为它适用于列表列表。这意味着您匹配的列表的头部也是一个列表。您可以将代码重写为以下更简单的版本:
let pack xs =
let collect x = function
| head::xss -> // Decompose into first element (head) and the rest (tail)
match head with
| y::xs when x = y -> (x::y::xs)::xss
| _ -> [x]::xss
| xss -> [x]::xss
List.foldBack collect xs []
现在您在代码中有一些重复,但是您可以看到collect
需要x
和另一个参数,将另一个参数与head::xss
匹配(以获取头/尾)然后还会分解head
。