我正忙着为一些小学教育学生建立一个ELO。
ELO中的一些问题是“开放式”,因此学生应在文本框中输入答案。
假设有一个问题,正确答案是" scanner"。一名学生写错字并输入" scaner"。我不想将此答案标记为不正确。
所以我想知道是否有一个操作员'类似于'在PHP中,与MariaDb Sql中的LIKE
或者双重'相同。在数学中。
我非常确定我的问题有解决方法,但我只是渴望学习。
答案 0 :(得分:5)
检查出来:
http://php.net/manual/en/function.levenshtein.php
Levenshtein算法对于这种确切的场景非常有用。它适用于拼写错误或大脑屁时刻,比如打“吹”而不是“蓝色”,名字等等。
Levenshtein将返回一个数字。这个数字表示两个单词之间的“距离”。我在你的场景中做的是用一个小数字,比如2或3来做最大距离。这样,如果只需要一个字符校正,那就没问题了。但是,如果单词是“Scanner”,并且他们输入“Skammer”,则它实际上不会将其作为有效响应传递。
以下是一些例子:
<?php
$threshold = 2;
$words = array('Scanner', 'Scaner', 'Skanner', 'Skammer', 'Clammer', 'Skaner');
$match = "Scanner";
foreach($words as $word){
echo levenshtein($match, $word) . "<br>";
}
以上将输出以下内容:
0
1
1
3
4
2
因此,您可以看到密切相关的单词与不那么紧密相关的单词之间的相关性。因此,有了上述阈值,如果我们稍微更改一下代码,我们就可以这样做:
<?php
$threshold = 2;
$words = array('Scanner', 'Scaner', 'Skanner', 'Skammer', 'Clammer', 'Skaner');
$match = "Scanner";
foreach($words as $word){
if(levenshtein($match, $word) <= $threshold) echo "$word is close enough to $match! <br>";
else echo "$word is NOT close enough to $match! <br>";
}
我们会得到这样的回复:
Scanner is close enough to Scanner!
Scaner is close enough to Scanner!
Skanner is close enough to Scanner!
Skammer is NOT close enough to Scanner!
Clammer is NOT close enough to Scanner!
Skaner is close enough to Scanner!
注意“Clammer”与“Scanner”的距离是4。让我解释一下。该距离是为了使单词匹配而必须更改的字符数量。所以,“C”必须改变,“L”必须改变,两个“M”都必须改变。因此,得分为4。
使用它时,请考虑“S”和“s”是两个完全不同的字符,所以它绝对区分大小写。我会让它不区分大小写,以确保像“ScAnNeR”这样的东西不会被标记为错误的答案。像这样:
<?php
$threshold = 2;
$words = array('ScAnNeR', 'Scaner', 'Skanner', 'Skammer', 'Clammer', 'Skaner');
$match = "Scanner";
foreach($words as $word){
if(levenshtein(strtolower($match), strtolower($word)) <= $threshold) echo "$word is close enough to $match! <br>";
else echo "$word is NOT close enough to $match! <br>";
}
谨慎的话
我高度建议不要依赖soundex()
。看看这个例子:
<?php
$threshold = 2;
$words = array('spectacular', 'spectacle');
$match = "spectacle";
foreach($words as $word){
if(levenshtein(strtolower($match), strtolower($word)) <= $threshold) echo "$word is close enough to $match! <br>";
else echo "$word is NOT close enough to $match! <br>";
echo soundex($word) . "/" . soundex($match) . "<br>";
}
该示例给出了这个结果:
spectacular is NOT close enough to spectacle!
S123/S123
spectacle is close enough to spectacle!
S123/S123
两个完全不同的单词甚至听起来都不一样,根据soundex()
,它们将是一个完美的匹配!虽然我认为它对某些应用程序来说是一个有用的功能,但它对于这种应用程序来说还不是一个很好的解决方案。这是另一个例子:
<?php
$threshold = 2;
$words = array('clancy', 'klancy');
$match = "clancy";
foreach($words as $word){
if(levenshtein(strtolower($match), strtolower($word)) <= $threshold) echo "$word is close enough to $match! <br>";
else echo "$word is NOT close enough to $match! <br>";
echo soundex($word) . "/" . soundex($match) . "<br>";
}
输出:
clancy is close enough to clancy!
C452/C452
klancy is close enough to clancy!
K452/C452
底线:不要依赖soundex()
这种应用程序。你最终只会与它战斗并在此过程中被烧毁。
答案 1 :(得分:1)
您可以使用PHP本机函数/main.css?v=2
。信息可以在这里找到:
http://php.net/manual/en/function.similar-text.php
有趣的是,您通过引用为最后一个参数传递变量。所以你会做类似的事情:
similar_text()
您可以指定similar_text($first, $second, $percent)
到接受的阈值。因此,如果它们与X%相似,则可以将其标记为正确。
答案 2 :(得分:1)
由于这是一项测试,我个人会要求拼写错误,没有拼写错误,但有两个很好的可能性,soundex()和similar_text():
var_dump(
soundex('scanner') == soundex('scaner')
);
收益率true
。
var_dump(
strlen('scanner') - similar_text('scanner', 'scaner')
);
收益率1
,因此您需要确定可接受的差异数量。
另一个更复杂的可能性是levenshtein(),尽管基于非常不同的假设正确答案来确定适当的距离将是一项任务。