我有一个csv文件,结构如下:
- 第一行是标题行
- 其余行是数据行,每行都有相同数量的逗号,因此我们可以按列来处理数据
我编写了一个小脚本来遍历文件的每一行,并返回一个元组序列,其中包含列标题和该列中最大数据字符串的长度:
let getColumnInfo (fileName:string) =
let delimiter = ','
let readLinesIntoColumns (sr:StreamReader) = seq {
while not sr.EndOfStream do
yield sr.ReadLine().Split(delimiter) |> Seq.map (fun c -> c.Length )
}
use sr = new StreamReader(fileName)
let headers = sr.ReadLine().Split(delimiter)
let columnSizes =
let initial = Seq.map ( fun h -> 0 ) headers
let toMaxColLengths (accumulator:seq<int>) (line:seq<int>) =
let chooseBigger a b = if a > b then a else b
Seq.map2 chooseBigger accumulator line
readLinesIntoColumns sr |> Seq.fold toMaxColLengths initial
Seq.zip headers columnSizes;
这个在小文件上运行良好。但是当它尝试处理一个大文件(> 75 Mb)时,它会因为 StackOverflow 异常而使 fsi 崩溃。如果我删除这一行
Seq.map2 chooseBigger accumulator line
程序执行完毕。
现在,我的问题是:为什么F#会占用堆栈?我对F#中的序列的理解是,整个序列不会被保存在内存中,只有正在处理的元素。因此,我期望已经处理过的行不会留在堆栈中。我的误解出在哪里?
Seq.map2 chooseBigger accumulator line |> Seq.toList |> seq
? - Daniel