F#,char seq - >字符串

时间:2013-02-02 23:52:24

标签: string f# char seq

一个快速的问题,可能更多的是咆哮(但我希望能够开悟)。

在F#中,字符串与Seq兼容,因此“abcd”|> Seq.map f将对字符串起作用。

这是处理字符串的绝佳工具,例如从字符串中取出前5个字符:

"abcdef01234567" |> Seq.take 5

或删除重复的字符:

"abcdeeeeeee" |> Seq.distinct

问题是,一旦你有了char seq结果,将它再次转换回字符串变得非常尴尬,String.concat“”要求成员是字符串,所以我最终做了很多:< / p>

"abcdef01234567" 
|> Seq.take 5
|> Seq.map string
|> String.concat ""

以至于我在90%的项目中使用了一个函数:

let toString : char seq -> string = Seq.map string >> String.concat ""

我觉得这已经超过了顶层,但在我想找到替代方案的任何地方,我遇到了令人发指的事情,比如StringBuilder或内联lambda并使用new:

"abcdef01234567" 
|> Seq.take 5
|> Seq.toArray 
|> fun cs -> new string (cs) (* note you cannot just |> string *)

我希望在语言中看到的(也许是疯狂的)期望当在字符串上使用Seq时,结果表达式中的类型签名应该是字符串 - &gt;串。意思是,出现的是什么。 “abcd”|&gt; Seq.take 3 =“abc”。

在这种情况下,我对高级字符串操作的期望是否有误?

有没有人建议以一种不错的方式接近这个,我觉得我必须遗漏一些东西。

4 个答案:

答案 0 :(得分:22)

我自己就是在研究这个问题。我发现System.String.Concat工作得很好,例如。

"abcdef01234567" |> Seq.take 5 |> String.Concat;;

假设您已打开System

答案 1 :(得分:11)

Seq模块中的函数只处理序列 - 也就是说,当您使用string调用它们时,它们只会“看到”Seq<char>并对其进行操作。即使他们进行了特殊检查以查看参数是否为string并采取了一些特殊操作(例如,仅针对字符串的函数的优化版本),他们仍然必须将其作为{{返回} 1}}安抚F#类型系统 - 在这种情况下,您需要在任何地方检查返回值,看看它是否实际上是Seq<char>

好消息是F#内置了一些您正在撰写的代码的快捷方式。例如:

string

可缩短为:

"abcdef01234567" |> Seq.take 5

其他一些你仍然需要使用"abcdef01234567".[..4] // Returns the first _5_ characters (indices 0-4). ,或编写自己的优化实现来操作字符串。

这是一个在字符串中获取不同字符的函数:

Seq

答案 2 :(得分:6)

F#有String module,其中包含一些专门用于字符串的Seq模块功能。

答案 3 :(得分:3)

自从5年前提出这个问题以来,F#已经获得了使用构造函数作为函数的能力。我会使用String(Char[])将字符转换为字符串。您可以转换为F#序列或F#列表,但我也可能只使用String.ToCharArray方法使用F#数组模块。

printfn "%s" ("abcdef01234567".ToCharArray() |> Array.take 5 |> String)

如果您真的想使用char seq,那么您可以将其传递给字符串,如下所示:

printfn "%s" ("abcdef01234567" |> Seq.take 5 |> Array.ofSeq |> String)