它适用于for循环和可变变量:
let addLnNum filename =
use outFile = new StreamWriter(@"out.txt")
let mutable count = 1
for line in File.ReadLines(filename) do
let newLine = addPre (count.ToString()) line
outFile.WriteLine newLine
count <- count + 1
Run Code Online (Sandbox Code Playgroud)
但它非常"无功能",所以我很好奇这样做的正确方法是什么?我想到如何将索引号附加到字符串列表:
let rec addIndex (startInd:int) l=
match l with
|x::xs -> startInd.ToString()+x :: (addIndex (startInd+1) xs)
|[] -> []
Run Code Online (Sandbox Code Playgroud)
但它不适用于File.ReadLines:
let addLnNum2 filename =
use outFile = new StreamWriter(@"out.txt")
File.ReadLines(filename)
|> addIndex 1
|> ignore
//Error 1 Type mismatch. Expecting a Collections.Generic.IEnumerable<string> -> 'a
//but given a string list -> string list
Run Code Online (Sandbox Code Playgroud)
将整个文件作为列表读入内存是唯一的方法吗?是否有类似seq.count的东西,所以它可以类似于以下内容?
let addLnNum3 filename =
use outFile = new StreamWriter(@"out.txt")
File.ReadLines(filename)
|> Seq.map (fun s -> Seq.count + s) //no such thing as Seq.count
|> Seq.iter outFile.WriteLine
|> ignore
Run Code Online (Sandbox Code Playgroud)
对于Seq模块中的某些功能(与List... 相同),您将找到带有附加功能的版本i- 例如,Seq.map您可以找到 Seq.mapi并且这是您正在寻找的 - 除了您收集的价值(作为第一个参数)索引也是:
let addLnNums filename =
use outFile = new System.IO.StreamWriter (@"out.txt")
System.IO.File.ReadLines filename
|> Seq.mapi (sprintf "%d: %s")
|> Seq.iter outFile.WriteLine
Run Code Online (Sandbox Code Playgroud)
还要注意的是,你并不需要ignore为Seq.iter已恢复() : unit
如果我们没有这个,那么功能方式将是这样使用Zip:
let addLnNum filename =
use outFile = new System.IO.StreamWriter (@"out.txt")
Seq.zip (Seq.initInfinite id) (System.IO.File.ReadLines filename)
|> Seq.map (fun (index, line) -> sprintf "%d: %s" index line)
|> Seq.iter outFile.WriteLine
Run Code Online (Sandbox Code Playgroud)
其中(除了解除功能之外map)基本相同
对于列表,你显然没有a List.initInfinte,所以只需要Seq- Seq.zip并且List.zip对于具有不同项目计数的集合有不同的行为 - Seq.zip当一个集合运行时停止尝试但是List.zip希望两个列表具有相同的大小并且如果两个列表具有相同的大小则会抛出异常不