如何在 F# 中递归打印出平均数的年份?
How do I print out year with average number recursively in F#?
好吧,为了解决这个令人头疼的问题几天,我试图弄清楚如何从我的文本文件中的每行中打印出年份和平均数。几天前我问过这个类似的问题,所以基本上我在问同样的问题,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
您拥有的代码实际上非常接近于提供您期望的数据。你可以做一些改变来简化事情。
第一个回答你的问题
Why does my program's output looks like this in the picture below?
这是因为您要打印出年份和所有已解析的值(这与刚刚打印出文件的代码不匹配)。解决这个问题的一个简单方法是让 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))
好吧,为了解决这个令人头疼的问题几天,我试图弄清楚如何从我的文本文件中的每行中打印出年份和平均数。几天前我问过这个类似的问题,所以基本上我在问同样的问题,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
您拥有的代码实际上非常接近于提供您期望的数据。你可以做一些改变来简化事情。
第一个回答你的问题
Why does my program's output looks like this in the picture below?
这是因为您要打印出年份和所有已解析的值(这与刚刚打印出文件的代码不匹配)。解决这个问题的一个简单方法是让 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))