【问题标题】:Javascript - How to know how much string matched in another string?Javascript - 如何知道另一个字符串中有多少字符串匹配?
【发布时间】:2019-01-13 02:23:39
【问题描述】:

我一直在实施一个简单的英语测验。在那,我们需要验证用户在输入字段中输入的答案。在当前的实现中,我正在将正确答案与用户的答案进行精确比较。喜欢,

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");
    }
}

但我不想完全验证。比如,忽略区分大小写、逗号、撇号等。例如,如果用户输入,

我不喜欢电影

答案可能是正确的。我不知道如何开始以及从哪里开始。请任何人帮忙。

【问题讨论】:

  • 问题的本质建议你要验证主观答案。目前,这项技术正在开发中。人们正试图通过人工智能来实现这一目标。所以我建议为一个问题写多个答案对你有用。
  • 因为“不!我不喜欢电影”也是正确答案。所以尝试使用数组检查答案是否在数组中,并及时更新数组。

标签: javascript regex string substring


【解决方案1】:

一种选择是去除所有非单词字符和空格,并比较每个替换字符串的小写版本:

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.");

另一种选择是遍历userInput 的所有可能子字符串,并找出与所需answer 重叠最多的子字符串,但这要复杂得多。

一个更简单的选择是检查有多少重叠的单词

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.");

【讨论】:

  • 它不符合问题中提出的条件
  • @CertainPerformance,我会将代码与我的网络应用程序集成。如果它有效并且如果我获得足够的声誉,我会举手,勾选你的答案并投票给你。
  • @DhananjaiPai 查看编辑,我认为计算重叠单词的数量可以工作
  • @CertainPerformance validate("不,我喜欢电影。");并且 validate(No I like movies) 将等同于 true,无论意图如何。第二种算法实际上是错误的。我已经为这项工作投票了第一个代码。
  • @Dhananjai Pai:写dontdo not 也很重要。如果有人写Nah, I do not enjoy movies,它的失败与Yes 相同。最后我会建议多选,这解决了每个用户如何写出不同答案的问题。
【解决方案2】:

如果您只想简单地发现拼写错误和小的变化,一个标准指标称为编辑距离或Levenshtein distance。这是将一个文本更改为另一个文本所需的最小删除、插入或替换次数的计数。诸如“不,我不喜欢电影”和“不,我不喜欢动作”之类的字符串将具有较小的编辑距离。

这是一个快速而肮脏的递归编辑距离函数,它会给你一个想法:

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){
    if(i == text.length && j == pattern.length) return 0
    if(i == text.length) return pattern.length - j
    if(j == pattern.length) return text.length - i   
    let choices = [
        (matrix[i+1][j+1] || (matrix[i+1][j+1] = editDistance(text, pattern, i+1, j+1))) + (text[i].toLowerCase() === pattern[j].toLowerCase() ? 0 : 1),
        (matrix[i+1][j]   || (matrix[i+1][j]   = editDistance(text, pattern, i+1, j))) + 1,
        (matrix[i][j+1]   || (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"))

选择一个可接受的最小距离非常适合匹配有小错别字的字符串。当然,如果您试图衡量用户意图,这些简单的色调都不会起作用。像“I love tacos”和“I loath tacos”这样的字符串有一个小的编辑距离,如果没有语言知识,你不能说它们的意思相反。如果您需要进行这种级别的检查,您可以尝试使用像 Watson Conversation 这样的服务,它将返回用户输入的意图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多