循环遍历2个元组的列表以替换字符串的一部分

时间:2014-06-15 05:21:43

标签: f#

我正在尝试用更多功能版本替换链式String.Replace()调用。原文:

let ShortenRomanNumeral (num : string) : string = 
    num.Replace("VIIII", "IX").Replace("IIII", "IV").Replace("LXXXX", "XC").Replace("XXXX", "XL").Replace("DCCCC", "CM").Replace("CCCC", "CD")

适用于一个键值对的功能版本:

let ShortenRomanNumeral' (str : string) (k : string) (v : string) : string =
    let strAfterReplace =
        str.Replace(k, v)
    strAfterReplace

我正在努力扩展它以使用元组列表,例如

let replacements = [("VIIII", "IX"); ("IIII", "IV"); ...]

如何编写此函数以将Replace()应用于替换列表中每个键和值的字符串?

2 个答案:

答案 0 :(得分:3)

折叠很好。但只是为了证明另一种方法......

// You can put the input string 
// as the LAST parameter not first
let shortenRomanNumeral (k:string,v:string) (input:string)  =
    input.Replace(k,v)

// This allows you to do partial application like this
let replace4 = shortenRomanNumeral ("IIII", "IV")
let replace9 = shortenRomanNumeral ("VIIII", "IX")

// replace9 and replace4 have the signature string->string
// they are now simple string transformation functions
replace4 "abcIIIIdef" |> printfn "result is '%s'"
replace9 "abcVIIIIdef" |> printfn "result is '%s'"

// and they can be composed together.
// Order is important. Do 9 before 4.
let replace4and9 = replace9 >> replace4 

replace4and9 "VIIII abc IIII" |> printfn "result is '%s'" 

// With this approach, you can now transform a list of tuples 
// into a list of string transforms using List.map
let listOfTransforms = 
    [("VIIII", "IX"); ("IIII", "IV");] 
    |> List.map shortenRomanNumeral 

// and you can combine all these into one big transformation 
// function using composition
let transformAll = 
    listOfTransforms 
    |> List.reduce (>>)

// finally you can apply the big function
transformAll "VIIII abc IIII" |> printfn "result is '%s'" 

答案 1 :(得分:2)

fold将完成这项工作:

let ShortenRomanNumeral' (str : string) (k : string, v : string) : string =
    let strAfterReplace =
        str.Replace(k, v)
    strAfterReplace

let replacements = [("VIIII", "IX"); ("IIII", "IV"); ]

let replaceValues str = List.fold ShortenRomanNumeral' str replacements

replaceValues "VI VII VIIII I II III IIII" // "VI VII IX I II III IV"

请注意,我只修改了ShortenRomanNumeral'的最后一个参数来接受tupled值。