我刚刚开始使用F#并试图了解典型的idoms和有效的思考和工作方式.
手头的任务是将制表符分隔文件简单转换为以逗号分隔的文件.典型的输入行将如下所示:
let line = "@ES# 01/31/2006 13:31:00 1303.00 1303.00 1302.00 1302.00 2514 0"
Run Code Online (Sandbox Code Playgroud)
我开始使用这样的循环代码:
// inFile and outFile defined in preceding code not shown here
for line in File.ReadLines(inFile) do
let typicalArray = line.Split '\t'
let transformedLine = typicalArray |> String.concat ","
outFile.WriteLine(transformedLine)
Run Code Online (Sandbox Code Playgroud)
然后我用一个Regex.Replace()替换了split/concat操作对:
for line in File.ReadLines(inFile) do
let transformedLine = Regex.Replace(line, "\t",",")
outFile.WriteLine(transformedLine)
Run Code Online (Sandbox Code Playgroud)
现在,最后,用管道替换了循环:
File.ReadLines(inFile)
|> Seq.map (fun x -> Regex.Replace(x, "\t", ","))
|> Seq.iter (fun y -> outFile.WriteLine(y))
// other housekeeping code below here not shown
Run Code Online (Sandbox Code Playgroud)
虽然所有版本都有效,但最终版本对我来说最直观.这是一个更有经验的F#程序员如何完成这项任务?
Tom*_*cek 12
我认为所有三个版本都是完美的,F#专家会写的惯用代码.
我通常更喜欢使用内置语言功能(如for循环和if条件)编写代码,如果他们让我解决我的问题.这些是必要的,但我认为当API需要命令式代码(如outFile.WriteLine)时使用它们是个好主意.如你所说 - 你从这个版本开始(我也会这样做).
使用高阶函数也很好 - 虽然我可能只在我想编写数据转换并获得新的序列或行列表时才会这样做- 如果您使用的是逐行File.WriteAllLines编写行,这将非常方便.虽然,也可以通过简单地使用序列表达式包装第二个版本来完成:
let transformed =
seq { for line in File.ReadLines(inFile) -> Regex.Replace(line, "\t",",") }
File.WriteAllLines(outFilePath, transformed)
Run Code Online (Sandbox Code Playgroud)
我认为没有任何客观理由可以选择其中一个版本.我个人的风格偏好是使用for和重构序列表达式(如果需要),但其他人可能不同意.