首页 > 解决方案 > F# 在没有第一个或最后一个元素的情况下优雅地折叠?

问题描述

假设您有一个字符串列表: [ "a"; “乙”;"c" ] 并且您想将其转换为单个字符串,如下所示: "a,b,c" 请注意缺少最后一个逗号。我发现这种情况一次又一次地出现在我身上,想想所有不允许尾随逗号出现的编程语言,你正在构建某种代码生成器。我通常会得到类似的结果:

let listOfThings = ["a";"b";"c"]
let folded =
    listOfThings
    |> List.map (fun i -> i + ",")
    |> List.fold (+) ""
    |> (fun s -> s.Substring(0, s.Length - 1))

我觉得已经有一些类似折叠的功能,因为这似乎是一个基本的用例,我只是不知道它的名字是什么,或者用什么名字来搜索它。

标签: f#fold

解决方案


Afold递归地将折叠函数应用于列表的所有值,从初始状态开始,在这种情况下您并不特别想要。

使用使用列表的头部作为其起始状态的 reduce 更简单:

listOfThings |> List.reduce (fun sum cur -> sum + "," + cur) // "a,b,c"

一个小缺点是,由于它使用列表头,因此使用空列表调用 reduce 会失败。您可以通过检查空列表来缓解这种情况。

正如您所描述的,没有任何内置函数,我们跳过为最后一个元素添加尾随逗号:

let rec join = function
| []    -> ""
| [x]   -> x
| x::xs -> x + ","  + join xs

["a"; "b"; "c"] |> join // a,b,c

但是,最有效的方法是使用String.Joinwhich 内部使用 a StringBuilder,而reduce为每次调用分配一个新字符串:

String.Join(",", listOfThings) // "a,b,c"

推荐阅读