user305904
user305904

Reputation: 37

finding average with list.fold

Just trying to make a really simple average float list -> float, that finds the average of a list. This is my code:

let list ls = List.fold (fun acc float -> acc + float) 0.0 ls;;

list [1.60; 2.30; 5.0; 2.30];;

The output is 11.2

I need something added to the function that can divide 11.2 with x elements to find the average.

Any help?

Upvotes: 0

Views: 1590

Answers (1)

Random Dev
Random Dev

Reputation: 52290

If you want to iterate the list only once you can just count up it's length in parallel (using a tuple `(sum, len)´ as an accumulator) and then divide afterwards:

let avg xs = 
   xs 
   |> List.fold (fun (sum,len) x -> (sum+x,len+1.0)) (0.0,0.0) 
   |> (fun (sum,len) -> sum / len)

which can be written in a point-free style if you like:

let avg = 
   List.fold (fun (sum,len) x -> (sum+x,len+1.0)) (0.0,0.0) 
   >> (fun (sum,len) -> sum / len)

this gives you:

> avg [1.0;2.0;3.0];;
val it : float = 2.0

but of course the easiest way to extent your function is to just get the length of the list and divide by it:

let avg ls = 
   List.fold (fun acc float -> acc + float) 0.0 ls / (float ls.Length)

for the list this will not make any difference - but you can extend the above version to seqs easily and there it will make a difference (iterate the seq once or twice):

let avg : float seq -> float = 
   Seq.fold (fun (sum,len) x -> (sum+x,len+1.0)) (0.0,0.0) 
   >> (fun (sum,len) -> sum / len)

Upvotes: 5

Related Questions