0

我有一些作为练习编写的运行长度编码代码

let rle s = 
    s
    |> List.map (fun x -> (x, 1))
    |> List.fold (fun acc x -> 
        match acc with 
            | [] -> [(x, 1)]
            | h::(x, n) -> h::(x, n+1)
            | h -> h::(x, 1)
        )
    |> List.map (fun (x, n) -> 
        match n with
            | 1 -> x.ToString()
            | _ -> x.ToString() + n.ToString()
        )

该模式h::(x, n) -> h::(x, n+1)无法编译。

有谁知道为什么?

4

3 回答 3

3

RLE(笑)

let rle (s: string) = 
  let bldr = System.Text.StringBuilder()
  let rec start = function
    | [] -> ()
    | c :: s -> count (1, c) s
  and count (n, c) = function
    | c1 :: s when c1 = c -> count (n+1, c) s
    | s -> Printf.bprintf bldr "%d%c" n c; start s
  start (List.ofSeq s)
  bldr.ToString()

let s1 = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"
let s2 = "12W1B12W3B24W1B14W"

rle s1 = s2 |> printfn "%b" //"true"
于 2013-02-12T21:07:27.123 回答
2

它无法编译,因为::模式匹配的第二个参数必须是 a list,但这里它是一个元组。一般来说,您似乎只是误解了headand tail。Head 是顶部元素,而 tail 是以下元素的列表。本质上交换它们就可以了:

|> List.fold (fun acc x -> 
    match acc with 
        | [] -> [(x, 1)]
        | (x0, n)::t when x0=x -> (x0, n+1)::t
        | t -> (x, 1)::t
    )
    []

注 1:正如@pad 所注意到的,List.fold需要一个参数,一个“引导”累加器开始。显然,它应该只是一个空列表,[].
注意2:您不能直接匹配x. 相反,您将其绑定到x0x0x.
注意 3:匹配空列表[]不是必需的,因为它可以很高兴地使用最后一个模式。

于 2013-02-12T18:58:52.433 回答
2

这不能回答您的问题,但是我很无聊并编写了一个您可能会发现更有启发性的实现——只需使用 Visual Studio 或 MonoDevelop 中的调试器逐步完成它。

let rec private rleRec encoded lastChar count charList =
    match charList with
    | [] ->
        // No more chars left to process, but we need to
        // append the current run before returning.
        let encoded' = (count, lastChar) :: encoded

        // Reverse the encoded list so it's in the correct
        // order, then return it.
        List.rev encoded'

    | currentChar :: charList' ->
        // Does the current character match the
        // last character to be processed?
        if currentChar = lastChar then
            // Just increment the count and recurse.
            rleRec encoded currentChar (count + 1) charList'
        else
            // The current character is not the same as the last.
            // Append the character and run-length for the previous
            // character to the 'encoded' list, then start a new run
            // with the current character.
            rleRec ((count, lastChar) :: encoded) currentChar 1 charList'

let rle charList =
    // If the list is empty, just return an empty list
    match charList with
    | [] -> []
    | hd :: tl ->
        // Call the implementation of the RLE algorithm.
        // The initial run starts with the first character in the list.
        rleRec [] hd 1 tl

let rleOfString (str : string) =
    rle (List.ofSeq str)

let rec printRle encoded =
    match encoded with
    | [] ->
        printfn ""
    | (length, c) :: tl ->
        printf "%i%O" length c
        printRle tl

let printRleOfString = rleOfString >> printRle

将代码粘贴到 F# 交互式中并使用 Wikipedia 示例进行运行长度编码

> printRleOfString "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";;
12W1B12W3B24W1B14W
val it : unit = ()
于 2013-02-12T20:01:07.243 回答