F# - 删除字符串中的第一个字符后的重复字符
问题描述:
我想要做的是删除字符串中特定给定字符的重复项,但让第一个字符保留。即:F# - 删除字符串中的第一个字符后的重复字符
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"
这是很容易从一个字符串中删除重复的,但有没有办法删除重复的,但让第一个重复的元素留在字符串中?
答
这里有一个办法:
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."
答
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而不是字符串形式给出的。
答
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
答
当设计一个功能,可考虑从制造它的参数一般收益。要通过迭代传递状态,禁止可变变量,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"
不熟悉F#但是,您可以通过迭代字符串来创建字符列表。使用Contains方法来检查一个字符是否已经存在。如果是这样,跳过,否则添加到列表 – Laazo
Azola的想法看起来不错,但我建议做一个集合,因为'List.contains'是O(N)。使用['Set.ofSeq'](https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/set.ofseq%5B't%5D-function-%5Bfsharp%5D),然后你应该能够在O(1)时间内进行查找。 – rmunn
你能告诉我们你试过了什么吗? – TheInnerLight