首页 > 解决方案 > 避免迭代的最佳方法

问题描述

我有一个字符串

testString = "Hello [1], my name is [2]"

我想替换它,所以它等于

Hello Maria, my name is My.

我有一个函数,它需要一个字符串和替换列表。然后根据需要遍历该列表替换。

let parse testString (replacements: list<string>) =
        let mutable result = testString

        for index = 1 to replacements.Length do
            result <- result.Replace("[" + (index).ToString() + "]", replacements.[index-1])

        result

parse testString ["Maria";"My"]

但是,由于我切换到 F# 的主要原因之一是避免迭代和可变性,那么解决这个问题的最佳方法是什么?

我考虑过字符串上的正则表达式替换回调或结果列表上的迭代器/映射(似乎是最好的方法)。

标签: f#

解决方案


以下是您可以用更惯用的 F# 解决问题的几种方法:

let testString = "Hello [1], my name is [2]"

let parse input replacements =
    replacements
    |> List.mapi (fun i s -> i + 1, s) //Create a tuple with the index and the string
    |> List.fold (fun (result: string) (i, s) -> result.Replace($"[{i}]", s)) input //Fold iterates through the list making the replacements recursively

let parse2 input replacements =
    let rec parse2' (input:string) (replacements:string list) i =
        match replacements with
        | [] -> input //Replacements are empty so return the input
        | s :: replacements -> 
            // Take the head element off the list using pattern matching
            // Make a recursive call after performing the replacement
            parse2' (input.Replace($"[{i}]", s)) replacements (i + 1)

    parse2' input replacements 1

printfn "%s" (parse testString [ "Maria"; "My" ])
printfn "%s" (parse2 testString [ "Maria"; "My" ])

请注意,您的代码没有什么特别的问题,F# 鼓励采用混合方法来解决问题。如果您限制它们的范围,可变性和“原始”迭代是没有问题的。在这种情况下,变量永远不会离开函数的范围,因此它与程序的其余部分无关。


推荐阅读