问题
I'm not sure where to begin with the checking of a string for n occurrences of a specific char. I've laid out the basic outline of what I assume to be the framework for the function but the contents I'm not sure about?
let countCharFromNth (getStr : string)(chkdChar : char) =
if getStr.Length >=1 then
else printfn "Not enough arguments"
回答1:
Here is a tail recursive loop version.
let countCharFromNth (getStr : string)(chkdChar : char) =
let rec loop i count =
if i < getStr.Length then
if getStr.[i] = chkdChar then loop (i+1) (count+1)
else loop (i+1) count
else count
loop 0 0
It will get translated into an imperative loop by the compiler as all function calls are in the tail (last) position. While longer than the other versions, this is the most performant way of doing it as it does not create unnecessary intermediate collections.
回答2:
TL;DR
The 'most idiomatic' way is probably @Mark Seemanns:
let count x = Seq.filter ((=) x) >> Seq.length
The TooLong part
Note that this function is fully generic: x:'a -> (seq<'a> -> int) when 'a : equality
, i.e. it counts occurrences of any x
in a sequence of 'a
s, as long as 'a
supports equality. Due to the right-hand side being a function, we also don't need to specify the string argument. This is called point-free style.
The function is constructed by turning the =
operator into a function by wrapping it in parentheses (think (=)
= fun x y -> x = y
), filtering the sequence with this predicate and calculating the resulting seq
s length, i.e.
let count x xs =
xs
|> Seq.filter (fun x' -> x' = x)
|> Seq.length
which is
let count x xs =
Seq.length(Seq.filter (fun x' -> x' = x) xs)
Of course you can also leverage 'the C# way':
let count' x xs = System.Linq.Enumerable.Count(xs, fun x' -> x' = x)
Here you can't just turn the equality operator (=)
into a predicate because the F# compiler needs to do some magic to turn the F# 'a -> bool
into a Func<'a, bool>
.
The usage is exactly the same:
count 'a' "abbbac"
or (more readable)
"abbbac" |> count 'a'
"abbac" |> count' 'b'
This (and better composability) is the reason functional programmers tend to reverse the order of arguments (count x xs
vs. count xs x
).
More exotic (and less performant) solutions:
let count'' (c : char) str =
(System.Text.RegularExpressions.Regex.Matches(str, string c)).Count
let count''' (c : char) str =
(String.length str) - (str.Replace(string c, "") |> String.length)
回答3:
Using fold is another option:
open System
let countCharFold targetChar =
Seq.fold (fun count ch -> if ch = targetChar then count + 1 else count) 0
[<EntryPoint>]
let main argv =
let text = "hello world"
let ch = 'l'
printfn "%d" (countCharFold ch text)
Console.ReadLine() |> ignore
0
来源:https://stackoverflow.com/questions/40022846/how-to-count-the-occurrence-of-a-specific-character-in-a-string