一个快速的问题,可能更多的是咆哮(但我希望能够开悟)。
在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”。
在这种情况下,我对高级字符串操作的期望是否有误?
有没有人建议以一种不错的方式接近这个,我觉得我必须遗漏一些东西。
答案 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)
printfn "%s" ("abcdef01234567".ToCharArray() |> Array.take 5 |> String)
如果您真的想使用char seq
,那么您可以将其传递给字符串,如下所示:
printfn "%s" ("abcdef01234567" |> Seq.take 5 |> Array.ofSeq |> String)