user2099345
user2099345

Reputation: 1

Compare items in two separate lists in f#

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

Answers (3)

rene
rene

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

Jack P.
Jack P.

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

Lee
Lee

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

Related Questions