Reputation: 321
//Return a tuple from a text file:
let ExtractFromLine (line:string) =
let strings = line.Split('\t') //data members are spaced by tab
let strlist = Array.toList(strings) //each data member is now a list of str
let year = System.Int32.Parse(strlist.Head) //year is first in file, so Head
let values = List.map System.Double.Parse strlist.Tail //tail are all values
let average = List.average values //not part of text file
let min = List.min values //not part of text file
let max = List.max values //not part of text file
(year, values, average, min, max) //return tuple with all info
//----------
let rec createList fileline =
if fileline = [] then
[]
else
let (year, values, average, min, max) = ExtractFromLine fileline.Head
let l = (year, values, average, min, max) :: createList fileline.Tail
l
//------------
let main argv =
let file = ReadFile "data.txt"
let biglist = createList file //recursive function to make a list of tuples
printfn"%A" biglist //This prints the year, all values, average, min, and max for each tuple created
I now have a giant list of tuples with all of the information that I need. Have I retained the possibility of accessing all elements inside and performing calculations on them? I program in C++, and the solution is doable in that language, but F# is so much more powerful in my opinion. I'm sure its possible, I'm just missing the basics.
For example, how do I print the average of all the values for all years? I'm thinking of a for loop, but I'm not sure how to iterate.
for(all tuples in biglist)
printfn"%A:%A" tuple.year tuple.average
It's wrong obviously, but I think you guys understand what I'm trying to do.
The above question involves pulling data from one tuple at a time across the list. What if I wanted to print the largest average?This would involve accessing each tuple's average data member and comparing them to return the largest one. Do I have to create another list containing these averages?
I learned about fst and snd but I had a hard time applying it to this example. You don't have to answer all questions if it is too much, but any help is greatly appreciated as I start out in this language, thank you
Upvotes: 0
Views: 3194
Reputation: 8782
You can loop in F# but it's a construct from imperative programming world. More idiomatic approach is to access items of the list recursively.
Below some sample code that creates tuples, constructs a list, and then access items and checks which one is bigger. Looking at your code the average was third item in the tuple. That's why I've added a trd
function. It takes a 5-item tuple and returns a third item.
The prcsLst
function takes 2 arguments: a list and a starting max value. The idea is that when processing the list we take the head (first item on the list), compare it's average with current max. Whichever is bigger is passed to the next recursive round together with list's tail (the list without the first item).In this case as the initial max I passed in the average of the first item.
You can run the example in F# Interactive to see the results.
// create sample tuples
let t1 = (2014, 35, 18, 5, 45)
let t2 = (2014, 32, 28, 8, 75)
let t3 = (2014, 25, 11, 9, 55)
let t4 = (2015, 16, 13, 2, 15)
let t5 = (2015, 29, 15, 1, 35)
// create sample list
let lst = [t1;t2;t3;t4;t5]
// a function to return third item in a tuple
let trd (_,_,t,_,_) = t
// process list recursively
let rec prcsLst l max =
match l with
| [] -> max
| hd::tl ->
if (trd hd) > max then
prcsLst tl (trd hd)
else
prcsLst tl max
// invoke the method on the sample list
// as a starting point use the first item in the list
prcsLst lst (trd t1);;
Upvotes: 3
Reputation: 66587
On a mobile so forgive me for not doing any code examples :)
I suspect that the missing piece of your puzzle is called pattern matching. In F# you address elements of a tuple like so:
let (y, v, Av, mn, mx) = mytuple
Note that you can also use this in function declarations, and when doing a 'match'.
(there is an exception for 'twoples' where you can use the functions 'fst' and 'snd')
Another thing you should play with is the |> operator.
Upvotes: 1