Javascript - How to know how much string matched in another string?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Javascript - How to know how much string matched in another string?



I have been implementing a simple quiz for English. In that, we need to validate answers, which are entered by users in input field. In the current implementation, I am comparing the correct answer with user's answer exactly. Like,



HTML


<input type="text" id="answer" />
<button onclick="validate()">Validate</button>



Javascript


var question = "Do you like movies?",
answer = "No, I don't like movies.";

function validate()
var userInput = document.getElementById('answer').value;
if(answer == userInput)
console.log("correct");
else
console.log("wrong");




But I don't want validate exactly. Like, ignore case sensitive, commas, apostrophe, etc. For example if user enters,



i dont like movies



The answer can be correct. I don't know how start and where to start. Anyone please help.





The essence of the question suggests that you want to verify the subjective answer. Currently, this technology is under development. People are trying to achieve this through AI. So I would suggest writing multiple answers for single question will work for you.
– Ullas Hunka
Aug 6 at 7:18





Because "No! movies are not liked by me" is also a correct answer. So try using an array check the answer is in the array and update the array in course of time.
– Ullas Hunka
Aug 6 at 7:21




2 Answers
2



One option would be to strip out all non-word characters and spaces, and compare the lower-case version of each replaced string:




var question = "Do you like movies?",
answer = "No, I don't like movies.";

const normalize = str => str
.replace(/[^w ]/g, '')
.toLowerCase();
function validate(userInput)
const noramlizedInput = normalize(userInput)
const noramlizedAnswer = normalize(answer);
if (noramlizedInput == noramlizedAnswer)
console.log("correct");
else
console.log("wrong");


validate('No i dont like movies');
validate("NO!!!!! I DON''t like movies.");



Another option would be to loop through all possible substrings of the userInput and figure out which has the most overlap with the desired answer, but that's a whole lot more complicated.


userInput


answer



An easier option would be to check to see how many overlapping words there are:




var question = "Do you like movies?",
answer = "No, I don't like movies.";

const normalize = str => str
.replace(/[^w ]/g, '')
.toLowerCase()
.split(/s+/)
function validate(userInput)
const noramlizedInputArr = normalize(userInput);
const noramlizedAnswerArr = normalize(answer);
const overlapCount = noramlizedInputArr.reduce((a, word) => (
a + Number(noramlizedAnswerArr.includes(word))
), 0);
console.log(overlapCount);
if (overlapCount >= 4)
console.log("correct");
else
console.log("wrong");


validate('No i dont like movies');
validate("NO!!!!! I DON''t like movies.");
validate("i dont like movies.");
validate("Yes I like movies.");





It fails the condition asked in the question
– Dhananjai Pai
Aug 6 at 7:17





@CertainPerformance, I will integrate code with my web app. If it works and If I get sufficient reputation I will raise my hand, tick your answer and upvote you.
– Harin Kommuri
Aug 6 at 7:25





@DhananjaiPai See edit, I think counting the number of overlapping words could work
– CertainPerformance
Aug 6 at 7:26





@CertainPerformance validate("No i do like movies."); and validate(No I like movies) will be equated to true regardless of the incorrect intent. The second algorithm is actually wrong. I had already upvoted the first code for the effort.
– Dhananjai Pai
Aug 6 at 7:33






@Dhananjai Pai: Also matters whether one writes dont or do not. If one writes Nah, I do not enjoy movies it fails the same as Yes. I would suggest multiple choice in the end, which solves the issue how every user can write an answer differently.
– Lain
Aug 6 at 7:35



dont


do not


Nah, I do not enjoy movies


Yes



If you are interested in simply catching spelling errors and small variations, a standard metric is called edit distance or Levenshtein distance. This is a count of the minimum number of deletions, insertions, or substitutions you need to change one text into another. Strings like "No I don't like the movies" and "No I don't like the moveys" will have small edit distances.



Here's a quick and dirty recursive edit distance function that will give you an idea:




function validate(text, pattern)
// some simple preprocessing
let p = pattern.toLowerCase().replace(/[^a-z]+/ig, '')
let t= text.toLowerCase().replace(/[^a-z]+/ig, '')

// memoize recursive algorithm
let matrix = Array.from(length: t.length + 1, () => )

function editDistance(text, pattern, i = 0, j = 0) (matrix[i][j+1] = editDistance(text, pattern, i, j+1))) + 1
]
return Math.min(...choices)

return editDistance(t, p)


// similar strings have smaller edit distances
console.log(validate("No I dont lik moves","No i dont like movies"))

// a little less similar
console.log(validate("Yes I like movies","No i dont like movies"))

// totally different
console.log(validate("Where is the bathroom","No i dont like movies"))

// careful -- small edit distance !== close meaning
console.log(validate("I do like tacos","I don't like tacos"))



Picking a minimum acceptable distance works pretty well for matching strings with small typos. Of course, if you are trying to gauge user intent, none of these simple hues tics will work. Strings like "I love tacos" and "I loath tacos" have a small edit distance and you can't tell that they mean the opposite without knowledge of the language. If you need to do this level of checking you can try using a service like Watson Conversation that will return user intents to input.


Watson Conversation






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

make 2 or more post in bootsrap

Store custom data using WC_Cart add_to_cart() method in Woocommerce 3

Firebase Auth - with Email and Password - Check user already registered