快速将文本数据读入数组

4
我在使用F#将文本文件读入浮点数数组时遇到了困难。由于文本文件包含许多其他数据类型,因此我无法使用CSV解析器,但我相信一定有一个简单的函数可以完成此操作。在Python中,我只需循环遍历所有感兴趣的行,并使用类似以下内容的方法将它们附加到现有数组上:Reading file string into an array (In a pythonic way)
arrays = []
i = 1
for line in open(your_file):
    if i > startOfNumericDataIndex
        new_array = np.array((array.float(i) for i in line.split(' '))) 
        arrays.append(new_array)
    i++

我试图遵循 F# 风格来避免循环,但以下尝试都无法实现:

let lines = System.IO.File.ReadLines(path) //Collection
let linesStringArray = lines |> Seq.toArray // String array
let linesFloatArray = linesStringArray |> Array.map (fun x -> float x)

我得到了错误FS0001: 这个表达式应该是'a list'类型,但是这里是'string'类型,我已经尝试过将它转换为字符串列表和其他类型的列表,但是没有成功。

这个方法看起来很有前途:如何将字符串数组转换为浮点数数组,并用Double.NaN替换非数字值?:但是我无法弄清楚如何使用所给出的答案:

let stringLine = [| "2.0"; "3.0"; "2.0"|]    
let stringLine2Float = Array.map float stringLine

刚刚出现了错误:“类型''a list'与类型'string'不匹配”。


你的 Python 代码中所建议的,这些行是否只是由空格分隔的浮点数列表? - Reed Copsey
@ReedCopsey 一旦我们到达文件中某个容易识别的点,之后所有内容都是由空格分隔的浮点数。已编辑 Python 代码以反映这一点。 - arthuritus
1个回答

2

我建议不要将这些行转换为数组,而是使用Seq.collect将所有行压缩成一个序列:

let lines = System.IO.File.ReadLines(path) //Collection
let linesFloatArray = linesStringArray 
|> Seq.skip startOfNumericDataIndex
|> Seq.collect (fun line -> line.Split(' '))
|> Seq.map (fun x -> float.Parse x)
|> Array.ofSeq

如果您想要一个二维数组,可以这样做:
let lines = System.IO.File.ReadLines(path) //Collection
let linesFloatArray = linesStringArray 
|> Seq.skip startOfNumericDataIndex
|> Seq.map (fun line -> line.Split(' ') |> Array.map (fun x -> float.Parse(x)))
|> Array.ofSeq

非常感谢。我添加了一个 Seq.skip(startOfNumeric) 的调用,因为正如我对 @ReedCopsey 提到的那样,这个数据并不是从文件的开头开始的,另外还加入了 Seq.filter(fun x -> x<>"") 来去掉一些空字符串,这些字符串会导致 float.parse 函数出错。 - arthuritus
@arthuritus String.Split有一个选项,可以删除空条目-这可能比额外的筛选器更好。 - Reed Copsey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接