Reputation: 477
Just for fun I read these interview questions and tried to find the solutions in both C# and F# and I struggle to do following in idiomatic F# without mutating a boolean value or using a regex:
You’re given a word string containing one or many $ symbols, e.g.: "foo bar foo $ bar $ foo bar $ " Question: How do you remove the second and third occurrences of $ from a given string?
My imperative F# solution with mutation:
let input = "foo bar foo $ bar $ foo bar $ "
let sb = new StringBuilder()
let mutable first = true
let f c=
if c='$' && first then first<-false
else sb.Append(c) |> ignore
input |> Seq.iter f
(And a C# one):
var input = "foo bar foo $ bar $ foo bar $ ";
var sb = new StringBuilder();
bool first = true;
input.ForEach(c => {
switch (c)
{
case '$' when first: first = false; break;
default: sb.Append(c);break;
};
});
Upvotes: 0
Views: 193
Reputation: 5004
let f (s:string) =
s.Split('$')
|> Seq.mapi (fun i t -> (if i > 3 || i = 1 then "$" else "") + t)
|> String.concat ""
and here is another one that scans every char
using tail recursion and seq
computational expression:
let f (s:string) =
let rec chars n input = seq {
match Seq.tryHead input with
| Some '$' -> if not(n = 1 || n = 2) then yield '$'
yield! Seq.tail input |> chars (n+1)
| Some c -> yield c
yield! Seq.tail input |> chars n
| None -> ()
}
chars 0 s
|> fun cs -> new string(Seq.toArray cs)
It may be longer but is probably more efficient than the first one.
Edit: Nope, it is not more efficient and it is not a tail recursion, probably because it happens inside a Computation Expression.
Upvotes: 4
Reputation: 10624
let f (s:string) =
s.Split('$')
|> Array.toList
|> function
| [] -> ""
| [ a ] -> a
| [ a; b ] -> a + "$" + b
| a :: b :: c :: rest -> a + "$" + b + c + (rest |> String.concat "$")
f "foo bar foo $ bar $ foo bar $ "
// "foo bar foo $ bar foo bar "
f "1 $ 2 $ 3 $ 4 $ 5 $"
//"1 $ 2 3 4 $ 5 $"
Note that this solution only removes the second and third instance of $
. If you want to remove all except the first one then replace String.concat "$"
with String.concat ""
Upvotes: 4