Reputation: 1
This is the example I'm working on:
let test =
[("Andy", ["d"; "a"; "d"; "c"; "b"; "d"; "c"; "a"; "a"; "c"; "a"; "d"; "a"; "a"; "d"; "e"]);
("Harry", ["b"; "d"; "c"; "b"; "c"; "b"; "a"; "a"; "d"; "b"; "d"; "d"; "a"; "c"; "b"; "e"]);
let answers = ["b"; "a"; "a"; "c"; "d"; "d"; "c"; "a"; "a"; "d"; "a"; "d"; "a"; "a"; "d"; "e"]);
I'm trying to use list.map to compare each persons test and determine how many answers they got right. Any help would be appreciated.
Upvotes: 0
Views: 1877
Reputation: 42434
Expanding a little bit with getting both good and wrong answer count this will work...
First map the results to handle each individual scorelist. Then fold2 with the correct awnserlist to find matches (you could use a simple if then here). I count the number of good and wrong answers in a tuple. The show function does a simple iter to get the fist and second item from the tuple and then printf the values.
let scores results corr =
results
|> List.map (
fun (name, score) ->
(name, List.fold2 (
fun s rhs lhs ->
match s with
| (good, wrong) when rhs=lhs -> ( good + 1 , wrong)
| (good, wrong) -> ( good, wrong + 1)
) (0, 0) score corr
)
)
let show scorelist =
scorelist
|> List.iter
( fun i ->
match i with
| (name, score) ->
match score with
| (good, wrong) ->
printf "%s correct: %d wrong: %d \r\n"
name
good
wrong
)
run from F# interactive:
show (scores test answers);;
Andy correct: 12 wrong: 4
Harry correct: 5 wrong: 11
Upvotes: 0
Reputation: 11525
This should do the trick:
let test =
[("Andy", ["d"; "a"; "d"; "c"; "b"; "d"; "c"; "a"; "a"; "c"; "a"; "d"; "a"; "a"; "d"; "e"]);
("Harry", ["b"; "d"; "c"; "b"; "c"; "b"; "a"; "a"; "d"; "b"; "d"; "d"; "a"; "c"; "b"; "e"]); ]
let answerKey = ["b"; "a"; "a"; "c"; "d"; "d"; "c"; "a"; "a"; "d"; "a"; "d"; "a"; "a"; "d"; "e"];
let score answerKey answers =
List.zip answerKey answers
|> List.sumBy (fun (key, answer) ->
if key = answer then 1 else 0)
let results =
test
|> List.map (fun (name, answers) ->
name, score answerKey answers)
If you put this into F# Interactive, the results will be:
val results : (string * int) list = [("Andy", 12); ("Harry", 5)]
Upvotes: 3
Reputation: 144136
I would create a function to calculate the score given a list of answers and the correct answers, then apply that to each tuple in your list:
let getScore ans correct = List.map2 (=) ans correct |> List.filter id |> List.length
let getCorrect l = l |> List.map (fun (name, ans) -> (name, getScore ans answers))
Upvotes: 5