好的,所以我已经解决了这个问题几天,试图弄清楚如何打印年份,我的文本文件中的每行平均数。几天前我问了这个类似的问题所以我基本上都在问同一个问题,How do I print out lines recursively from a text file along with the average value of total elements from per line?
这种情况继续下去。但是,我创建了几个函数。现在,这是我的新问题。为什么我的程序输出在下图中如下所示?我在我的代码中注释了几个问题。我一直期待输出像
2010: 3.5788888
2009: 4.697858
This list goes on recursively.
这是我更新的代码:
let ReadFile filename =
[ for line in System.IO.File.ReadLines(filename) -> line ]
let ParseLine (line:string) =
let strings = line.Split('\t')
let strlist = Array.toList(strings)
let year = System.Int32.Parse(strlist.Head)
let values = List.map System.Double.Parse strlist.Tail
(year, values)
let rec print (year, values) =
if values = [] then
()
else
printfn "%A: %A" year values.Head
print (year, values.Tail)
let avg (values:double list) = //this function can compute the average, but it wont work when I do in main, print(firstYear, avg (firstYear1))
let rec sum values accum =
match values with
| [] -> accum
| head :: tail -> sum tail (accum + head/12.0)
sum values 0.0
let rec sum (year, values:double list) =
if values = [] then
0.0
else
values.Head + sum (year, values.Tail)
[<EntryPoint>]
let main argv =
// read entire file as list of strings:
let file = ReadFile "rainfall-midway.txt"
printfn "** Rainfall Analysis Program **"
printfn ""
// let's parse first line into tuple (year, list of rainfall values),
// and then print for debugging:
let (year, values) = ParseLine file.Head
let firstYear = file.Head
let firstYear1 = file.Tail
//let data = List.map ParseLine file //I know map would be the key, but how does this work with year and its elements?
//let firstYear = data.Head
//let firstYear = data.Head
//print firstYear
print (firstYear, firstYear1)
//let S = sum firstYear
//printfn "%A" S
//let A = S / 12.0
//printfn "%A" A
// done:
printfn ""
printfn ""
0 // return 0 => success
答案 0 :(得分:1)
您拥有的代码实际上非常接近于为您提供所期望的数据。您可以进行一些更改以简化操作。
首先回答你的问题
为什么我的节目输出在下图中如下所示?
这是因为您打印出年份和所有已解析的值(这与打印文件的代码不匹配)。解决此问题的一种简单方法是让ParseLine
函数计算平均值。您需要在avg
函数之前移动ParseLine
,但这应该不是问题。
let avg (values:double list) =
let rec sum values accum =
match values with
| [] -> accum
| head :: tail -> sum tail (accum + head/12.0)
sum values 0.0
let ReadFile filename =
[ for line in System.IO.File.ReadLines(filename) -> line ]
let ParseLine (line:string) =
let strings = line.Split('\t')
let strlist = Array.toList(strings)
let year = System.Int32.Parse(strlist.Head)
let values = List.map System.Double.Parse strlist.Tail
(year, avg values) // calculate avg here
完成后,您可以使用地图在文件的所有行上运行ParseLine。
let result = file |> List.map ParseLine
然后打印出结果,只需遍历结果列表。
result |> List.iter(fun (year, avgRainfall) -> printfn "%i: %f" year avgRainfall)
那说我们可以完全删除sum和avg函数,并在我们的ParseLine
函数中使用fold。
let ParseLine (line:string) =
let strings = line.Split('\t')
let strlist = Array.toList(strings)
let year = System.Int32.Parse(strlist.Head)
year, (strlist.Tail |> List.fold(fun state el -> (System.Double.Parse el + state)) 0.0) / float strlist.Tail.Length
如果您不想更改ParseLine
功能,则可以执行以下操作:
let result = file |> List.map(fun el ->
let (year, values) = ParseLine el
(year, avg values))