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

发布于 2024-10-15 14:10:52 字数 313 浏览 0 评论 0原文

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

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

会产生输出

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

How can I best create a function (lets call it myPrint) that takes sprintf, a format string, and a list of strings as arguments and produces a result such that each element in the list of strings is applied/folded into sprintf?

i.e.

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

would produce the output

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

北方的巷 2024-10-22 14:10:52

请注意,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" 数量与列表中的字符串数量不匹配,这将在运行时引发异常。

Note that format strings in F# are specifically designed to take a statically known number of arguments, so there's not a particularly elegant way to do what you want. However, something like this should work:

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"]

This will throw an exception at runtime if the number of "%s"es in your string doesn't match the number of strings in the list.

遥远的绿洲 2024-10-22 14:10:52
List.map myPrint ["first"; "second"; "third;"]

将返回一个新的 sprintf'ed 列表...

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

map 采用 'T -> 'U - 并将任何格式的列表转换为任何其他格式
所以

let myPrint in = sprintf "%s" in

是允许的,但再次阅读你的问题 - 它没有达到你想要的效果。
- 你可以使用mapi,它在 (int -> 'T -> 'U) 中添加索引,并让你将 myPrint 定义为

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

Which will return ["1 : first"; “2:第二”; "3 : Third"] 越来越接近了......

但看起来你想要返回一个字符串 - 所以要么在其输出上使用 String.Join - 或使用折叠:

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

Will return a new sprintf'ed List...

To just print out to console... List.iter will iterate a function over each value in a list, and perform that function - but will only work with functions that don't return a value. (i.e. printf...)

map takes an 'T -> 'U - and will convert a list of any format into any other
So

let myPrint in = sprintf "%s" in

would be allowed, but reading your question again - it doesn't do what you want.
- you could use mapi, which adds the index in (int -> 'T -> 'U) and would let you define myPrint as

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

Which would return ["1 : first"; "2 : second"; "3 : third"] which is getting closer...

But it looks like you want a single string returned - so either to String.Join on the output of that - or use fold:

let final = List.fold (fun (builder, index) in -> builder.AppendFormat("{0}: {1}", index, in), index + 1) (new StringBuilder()) ["first"; "second"; "third"]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文