0

I am working in react on an Exam app. I have two arrays one with the user's given answers and one with correct answers. Comparing them is not showing the correct results. I am using hooks and the code is inside the useEffect hook. The result is also not showing the correct number of questions.

questions = [
{Qid: 1, Question: "This is question 1",
     Answers:[{Ans1:"Answer1",IsCorrect:true}
          {Ans2:"Answer2",IsCorrect:false}
          {Ans3:"Answer3",IsCorrect:false}
          {Ans4:"Answer4",IsCorrect:false}]},
{Qid: 2, Question: "This is question 2",
     Answers:[{Ans1:"Answer1",IsCorrect:false}
          {Ans2:"Answer2",IsCorrect:true}
          {Ans3:"Answer3",IsCorrect:false}
          {Ans4:"Answer4",IsCorrect:false}]},
{Qid: 3, Question: "This is question 3",
     Answers:[{Ans1:"Answer1",IsCorrect:true}
          {Ans2:"Answer2",IsCorrect:false}
          {Ans3:"Answer3",IsCorrect:false}
          {Ans4:"Answer4",IsCorrect:false}]},
{Qid: 4, Question: "This is question 4",
     Answers:[{Ans1:"Answer1",IsCorrect:false}
          {Ans2:"Answer2",IsCorrect:false}
          {Ans3:"Answer3",IsCorrect:true}
          {Ans4:"Answer4",IsCorrect:false}]}
]


keyquestions = [
{Qid: 1, Question: "This is question 1",
     Answers:[{Ans1:"Answer1",IsCorrect:false}
          {Ans2:"Answer2",IsCorrect:true}
          {Ans3:"Answer3",IsCorrect:false}
          {Ans4:"Answer4",IsCorrect:false}]},
{Qid: 2, Question: "This is question 2",
     Answers:[{Ans1:"Answer1",IsCorrect:false}
          {Ans2:"Answer2",IsCorrect:true}
          {Ans3:"Answer3",IsCorrect:false}
          {Ans4:"Answer4",IsCorrect:false}]},
{Qid: 3, Question: "This is question 3",
     Answers:[{Ans1:"Answer1",IsCorrect:true}
          {Ans2:"Answer2",IsCorrect:false}
          {Ans3:"Answer3",IsCorrect:false}
          {Ans4:"Answer4",IsCorrect:false}]},
{Qid: 4, Question: "This is question 4",
     Answers:[{Ans1:"Answer1",IsCorrect:false}
          {Ans2:"Answer2",IsCorrect:true}
          {Ans3:"Answer3",IsCorrect:false}
          {Ans4:"Answer4",IsCorrect:false}]}
]

I am using react hooks and the code of the component is

const Results = (props) => {

const [questions, setQuestions] = useState(props.quest);
const [keyq, setKey] = useState(props.keyq);
const [correctAnswers, setCorAns] = useState(0);
const [wrongAnswers, setWrong] = useState(0);
const [once, setOnce] = useState(true);

useEffect(() => {

    if(once){
    for (let index = 0; index < questions.length; index++) {
        var qa = questions[index].Answers;
        var ka = keyq[index].Answers;

        var k = JSON.stringify(ka);
        var q = JSON.stringify(qa);

        if (k === q) {
            var cor = correctAnswers;
            cor = cor + 1;
            setCorAns(cor)
        } else {
            var wr = wrongAnswers;
            wr = wr + 1;
            setWrong(wr + 1)
        }
    }
}
setOnce(false);

},[correctAnswers,keyq,questions,wrongAnswers,once])

return (
        <div>
            <h4>Right: {correctAnswers}</h4>
            <h4>Wrong: {wrongAnswers}</h4>
            </div>
    )
    }
    
    export default Results
Hasan Zubairi
  • 1,037
  • 4
  • 23
  • 57
  • what is `keyquestions`? Where i can find user's given answers? – Girish Sasidharan Jun 28 '20 at 06:04
  • The array "questions" is from user and the array "keyquestions" is the correct answer key. – Hasan Zubairi Jun 28 '20 at 06:09
  • Your answer object is too complex, you need to simplify that too `[{ "Qid": 1, "answer" : "user selected answer"}]`. Then it will be easy to check with answer array. We can achieve with this structure too. but I suggest to restructure your answer array. – Girish Sasidharan Jun 28 '20 at 06:13
  • Does this answer your question? [Object comparison in JavaScript](https://stackoverflow.com/questions/1068834/object-comparison-in-javascript) – Siraj Alam Jun 28 '20 at 06:52

3 Answers3

0

You can apply filter here, One solution could be finding the index and matching if both are same means answer is true, other solution could be applying every on answers and checking if isCorrect values are as same as the question, if it same means true otherwise false. Here is a working example.

var questions = [{Qid: 1, Question: "This is question 1", Answers:[{Ans1:"Answer1",IsCorrect:true}, {Ans2:"Answer2",IsCorrect:false}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 2, Question: "This is question 2", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:true}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 3, Question: "This is question 3", Answers:[{Ans1:"Answer1",IsCorrect:true}, {Ans2:"Answer2",IsCorrect:false}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 4, Question: "This is question 4", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:false}, {Ans3:"Answer3",IsCorrect:true}, {Ans4:"Answer4",IsCorrect:false}]}];
var keyquestions = [{Qid: 1, Question: "This is question 1", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:true}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 2, Question: "This is question 2", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:true}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 3, Question: "This is question 3", Answers:[{Ans1:"Answer1",IsCorrect:true}, {Ans2:"Answer2",IsCorrect:false}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 4, Question: "This is question 4", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:true}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]}];

var result = questions.filter(k=>keyquestions.find(p=>p.Qid==k.Qid && p.Answers.findIndex(l=>l.IsCorrect)==k.Answers.findIndex(m=>m.IsCorrect))).length;

var result2 = questions.filter(k=>keyquestions.find(p=>p.Qid==k.Qid && p.Answers.every((l,i)=>l.IsCorrect==k.Answers[i].IsCorrect))).length;

console.log(`Total Correct answers are : ${result}`);
console.log(`Total Correct answers are : ${result2}`);

I hope this helps.

gorak
  • 5,233
  • 1
  • 7
  • 19
0

Try this. But its better if you can change the data structure. Do you really need to user Ans1, Ans2, Ans3 as keys ? You can do it Like this {Ans:"Answer4",IsCorrect:false}. If you cannot do that below code should work

import React, {useState, useEffect} from "react";
import "./styles.css";

const quest = [] // user_ans

const keyquest = [] // marking scheme

export default function App() {
  const [questions, setQuestions] = useState(quest);
  const [keyq, setKey] = useState(keyquest);
  const [correctAnswers, setCorAns] = useState(0);
  const [wrongAnswers, setWrong] = useState(0);
  const [once, setOnce] = useState(true);

  useEffect(() => {
    if(once) {
      keyq.map(q => {
        const user_q = questions.filter(user_q => user_q.Qid === q.Qid);

        // Get the correct answer of the question
        const marking_scheme_ans = q.Answers.filter(ans => ans.IsCorrect);
        const user_ans = user_q[0].Answers.filter(ans => ans.IsCorrect);
        
       // Because you used different keys for 4 answers as `ans1, ans2, ans3, ans4`
        const correct_answer_keys = Object.keys(marking_scheme_ans[0]).filter(key => key !== 'IsCorrect');
        const user_ans_keys = Object.keys(user_ans[0]).filter(key => key !== 'IsCorrect');;

        if(correct_answer_keys[0] === user_ans_keys[0]) {
          return setCorAns(c => c+1);
        } else {
          return setWrong(w => w +1);
        }
          
      })
    }
  }, [keyq,questions,once])

  return (
    <div>
        <h4>Right: {correctAnswers}</h4>
        <h4>Wrong: {wrongAnswers}</h4>
    </div>
  )
}
Dilshan
  • 2,797
  • 1
  • 8
  • 26
0

I have done the comparison based on the inputs you give and its work well.

But I would recommend some structural changes to your answer array and the question array, That will improve the performance. This structure help you to scale the system very easily.

  1. The answer array need to structured like below

    [{ "Qid": 1, "answer" : "user selected answer"}, { "Qid": 2, "answer" : "user selected answer"}]

  2. The question array should change like below

     [{Qid: 1, Question: "This is question 1",
    Answers:[{"option":"Answer1",IsCorrect:false}, 
       {"option":"Answer2",IsCorrect:true},{"option":"Answer3",IsCorrect:false}
       {"option":"Answer4",IsCorrect:false}]}]
    

let userAnswers = [{Qid: 1, Question: "This is question 1", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:false}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 2, Question: "This is question 2", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:true}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 3, Question: "This is question 3", Answers:[{Ans1:"Answer1",IsCorrect:true}, {Ans2:"Answer2",IsCorrect:false}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 4, Question: "This is question 4", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:false}, {Ans3:"Answer3",IsCorrect:true}, {Ans4:"Answer4",IsCorrect:false}]}];


let keyquestions = [{Qid: 1, Question: "This is question 1", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:true}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 2, Question: "This is question 2", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:true}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 3, Question: "This is question 3", Answers:[{Ans1:"Answer1",IsCorrect:true}, {Ans2:"Answer2",IsCorrect:false}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]},{Qid: 4, Question: "This is question 4", Answers:[{Ans1:"Answer1",IsCorrect:false}, {Ans2:"Answer2",IsCorrect:true}, {Ans3:"Answer3",IsCorrect:false}, {Ans4:"Answer4",IsCorrect:false}]}];
let result = {
"right" : 0, "wrong" : 0, "unattempted" :0
};


result = userAnswers.reduce((res, i) => {
  let user = i.Answers.filter(a =>  !!a.IsCorrect);
  let question = keyquestions.filter(k => k.Qid == i.Qid)[0];
  let actualAnswer = question.Answers.filter(a =>  !!a.IsCorrect)[0];
  if(!!user && user.length) {
  user[Object.keys(user)[0]] == actualAnswer[Object.keys(actualAnswer)[0]] ? res.right++ : res.wrong++;
  } else {
    res.unattempted++;
  }
  return res;
}, result);

console.log(result);
Girish Sasidharan
  • 582
  • 1
  • 5
  • 14