F # решение без мутации - PullRequest
       113

F # решение без мутации

0 голосов
/ 16 октября 2018

Просто для удовольствия я прочитал эти вопросы интервью и попытался найти решения как в C #, так и в F #, и я изо всех сил стараюсь следовать в идиоматическом F #, не изменяя логическое значение и не используя регулярное выражение:

Вам дана строка слова, содержащая один или несколько символов $, например: "foo bar foo $ bar $ foo bar $" Вопрос: Как удалить второе и третье вхождения $ иззаданная строка?

Мой императив F # решение с мутацией:

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

(и 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;
    };
});

Ответы [ 2 ]

0 голосов
/ 17 октября 2018
let f (s:string) =
    s.Split('$')
    |> Seq.mapi (fun i t -> (if i > 3 || i = 1 then "$" else "") + t)
    |> String.concat ""

, а вот еще один, который сканирует каждую char, используя tail рекурсию и seq вычислительное выражение:

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)

Может быть длиннее , новероятно, более эффективен, чем первый .

Редактировать: Нет, это не более эффективно, и это не хвостовая рекурсия, вероятно, потому что это происходит внутри Вычислительного выражения.

0 голосов
/ 16 октября 2018
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 $"

Обратите внимание, что это решение удаляет только второй и третий экземпляр $.Если вы хотите удалить все, кроме первого, замените String.concat "$" на String.concat ""

...