“问题9”:打包清单

时间:2013-02-13 22:40:27

标签: list f# pattern-matching matching packing

我正在学习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 []

2 个答案:

答案 0 :(得分:1)

(y::xs)::xss匹配(非空)列表列表,yxs是第一个子列表的头部和尾部,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