【问题标题】:Chaining string.replace in F#在 F# 中链接 string.replace
【发布时间】:2018-06-18 10:55:37
【问题描述】:

我有一个带有一些标记的字符串,如下所示:

"There are two things to be replaced.  {Thing1} and {Thing2}"

我想用不同的值替换每个标记,所以最终结果如下所示:

"There are two things to be replaced.  Don and Jon"

我创建了一个像这样链接 String.Replace 的函数

let doReplacement (message:string) (thing1:string) (thing2:string) =
    message.Replace("{Thing1}", thing1).Replace("{Thing2}", thing2)

问题是当我链接 .Replace 时,值必须保持在同一行。这样做不起作用:

let doReplacement (message:string) (thing1:string) (thing2:string) =
    message
    .Replace("{Thing1}", thing1)
    .Replace("{Thing2}", thing2)

为了让我做一个多线链,我在想这样的事情:

message
|> replaceString "{Thing1}" thing1
|> replaceString "{Thing2}" thing2

具有这样的支持功能:

let replaceString (message:string) (oldValue:string) (newValue:string) =
    message.Replace(oldValue, newValue)

但是,这不起作用。有没有其他方法可以解决这个问题?

【问题讨论】:

    标签: f#


    【解决方案1】:

    通过使用|>,管道值被发送到最右边的未绑定参数(|> 管道值被发送到thing2)。 通过颠倒参数的顺序,它可以按预期工作。

    let replaceString (oldValue:string) (newValue:string) (message:string) =
        message.Replace(oldValue, newValue)
    
    let message = "There are two things to be replaced.  {Thing1} and {Thing2}"
    let thing1 = "Don"
    let thing2 = "Jon"
    
    message
    |> replaceString "{Thing1}" thing1
    |> replaceString "{Thing2}" thing2
    |> printfn "%s"
    

    【讨论】:

    • 我通常这样做,虽然我已经把函数放在String模块下的一个公共库中,所以它只是String.replace。该库在 NuGetGitHub 上以 CurryOn.Common 的形式提供。
    【解决方案2】:

    如果您缩进方法调用,它将编译:

    let doReplacement (message:string) (thing1:string) (thing2:string) =
        message
            .Replace("{Thing1}", thing1)
            .Replace("{Thing2}", thing2)
    

    这是我在 C# 中经常看到的一种风格,对我来说似乎很合乎逻辑。

    【讨论】:

    • 我会将message 放在参数列表的末尾。这对于 F#(最后最重要的参数)来说会更惯用,并且如果需要,可以启用 doReplacement 的流水线。
    【解决方案3】:

    您也可以通过折叠来完成此操作(尽管需要在列表/地图中输入。如果您要进行一致的替换,则更有用,但您可能并非如此)

    let replacements =
        [ "{thing1}", "Don"
          "{thing2}", "Jon" ]
    
    let replaceString (input: string) : string = 
        replacements 
        |> List.fold (fun acc (oldText, newText) -> acc.Replace(oldText, newText)) input
    

    或者更一般的情况,输入替换作为参数(这次说是地图)

    let replaceString (replaceMap: Map<string, string>) (input: string) : string =
        replaceMap
        |> Map.fold (fun acc oldText newText -> acc.Replace(oldText, newText)) input
    

    【讨论】:

      猜你喜欢
      • 2015-12-13
      • 2020-07-07
      • 2021-12-03
      • 2018-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-10
      • 1970-01-01
      相关资源
      最近更新 更多