F#将sprintf应用于字符串列表

时间:2011-02-01 11:14:17

标签: f# recursion functional-programming

如何最好地创建一个函数(让我们称之为myPrint),它将sprintf,一个格式字符串和一个字符串列表作为参数,并生成一个结果,以便将字符串列表中的每个元素应用/折叠到sprintf中?

即。

myPrint (sprintf "one: %s two: %s three: %s") ["first"; "second"; "third"];;

会产生输出

val myPrint : string = "one: first two: second three: third"

2 个答案:

答案 0 :(得分:8)

请注意,F#中的格式字符串专门用于获取静态已知数量的参数,因此没有一种特别优雅的方法可以执行您想要的操作。但是,这样的事情应该有效:

let rec myPrintHelper<'a> (fmt:string) : string list -> 'a = function
| [] -> sprintf (Printf.StringFormat<_>(fmt))
| s::rest -> myPrintHelper<string -> 'a> fmt rest s

let myPrint fmt = myPrintHelper<string> fmt

myPrint "one: %s two: %s three: %s" ["first"; "second"; "third"]

如果字符串中"%s" es的数量与列表中的字符串数不匹配,则会在运行时抛出异常。

答案 1 :(得分:0)

List.map myPrint ["first"; "second"; "third;"]

将返回一个新的sprintf'ed List ...

要打印到控制台... List.iter将在列表中的每个值上迭代一个函数,并执行该函数 - 但仅适用于不返回值的函数。 (即printf ...)

地图采用'T - &gt; 'U - 并将任何格式的列表转换为任何其他格式 所以

let myPrint in = sprintf "%s" in

会被允许,但是再次阅读你的问题 - 它不会做你想要的。 - 你可以使用mapi,它在(int - &gt;'T - &gt;'U)中添加索引,并允许你将myPrint定义为

let myPrint index val = sprintf "%d : %s" index val

哪会返回[“1:first”; “2:秒”; “3:第三”越来越近了......

但是看起来你想要返回一个字符串 - 所以要么输出那个String.Join - 或者使用fold:

let final = List.fold (fun (builder, index) in -> builder.AppendFormat("{0}: {1}", index, in), index + 1) (new StringBuilder()) ["first"; "second"; "third"]