F# - 首先在字符串中删除重复的字符

时间:2017-02-27 12:13:02

标签: string f#

我要做的是删除字符串中特定给定char的重复项,但保留第一个char。我:

let myStr = "hi. my .name."

//a function that gets a string and the element to be removed in the string
someFunc myStr "."  

其中someFunc返回字符串showen,如下所示:

"hi. my name"

从字符串中删除重复项很容易,但有没有办法删除重复项,但是让第一个重复元素保留在字符串中?

4 个答案:

答案 0 :(得分:4)

这是一种方法:

let keepFirst c s =
    Seq.mapFold (fun k c' -> (c', k||c<>c'), k&&c<>c') true s
    |> fst
    |> Seq.filter snd
    |> Seq.map fst
    |> Array.ofSeq
    |> System.String

let example = keepFirst '.' "hi. my .name."

答案 1 :(得分:3)

let someFunc (str : string) c =
    let parts = str.Split([| c |])
    if Array.length parts > 1 then
        seq {
            yield Array.head parts
            yield string c
            yield! Array.tail parts
        }
        |> String.concat ""
    else
        str

请注意,该字符以char而非字符串形式给出。

答案 2 :(得分:2)

let someFunc chr (str:string) =
    let rec loop (a: char list) b = function
        | [] -> a |> List.rev |> System.String.Concat
        | h::t when h = chr -> if b then loop a b t 
                               else loop (h::a) true t
        | h::t -> loop (h::a) b t
    loop [] false (str.ToCharArray() |> Array.toList)

请注意,该字符以char而非字符串形式给出。

编辑:另一种方法是使用正则表达式

open System.Text.RegularExpressions

let someOtherFunc c s =
    let pat = Regex.Escape(c)
    Regex.Replace(s, sprintf "(?<=%s.*)%s" pat pat, "")

请注意,在这种情况下,字符以字符串形式给出。

编辑2:

let oneMoreFunc (c:char) (s:string) =
    let pred = (<>) c
    [ s |> Seq.takeWhile pred
      seq [c]
      s |> Seq.skipWhile pred |> Seq.filter pred ]
    |> Seq.concat
    |> System.String.Concat

答案 3 :(得分:0)

在设计函数时,考虑使其参数具有通用性的收益。为了通过迭代传递状态,除了可变变量,Seq.scan可能是一个选择的武器。它折叠成一个新状态和一个选项的元组,然后Seq.choose去除状态和不需要的元素。

就功能构建块而言,让它接受谓词函数'a -> bool并让它返回一个函数seq<'a> -> seq<'a>

let filterDuplicates predicate =
    Seq.scan (fun (flag, _) x ->
        let p = predicate x in flag || p,
        if flag && p then None else Some x ) (false, None)
    >> Seq.choose snd

然后可以轻松地重复使用它来执行其他操作,例如0 together with odd numbers

filterDuplicates (fun i -> i % 2 = 0) [0..10]
// val it : seq<int> = seq [0; 1; 3; 5; ...]

通过调用相等运算符并将其输入System.String的构造函数,您将获得所需的签名char -> seq<char> -> System.String

let filterDuplicatesOfChar what s = 
    System.String(Array.ofSeq <| filterDuplicates ((=) what) s)
filterDuplicatesOfChar '.' "hi. my .name."
// val it : string = "hi. my name"