我正在构建一个简单的谷歌“你的意思是什么?”使用Levenshtein距离算法搜索建议。我已经设法让它工作,但我有返回结果的问题。
例如,如果关键字是“如何使用 fasebuk 和 twitster ?”我想只替换不正确的单词,以便建议结果为“如何使用 facebook 和 twitter ?”
如何实现这种建议?
以下是我到目前为止所做的事情:
public function searchsuggestion(Request $request)
{
$allwords = array('facebook','orkut','twitter','yahoo', 'microsoft','paypal','google','bing','msn');
$shortest = -1;
$keywords = trim($request->input('q'));
if (! empty($keywords)) {
foreach ($allwords as $word) {
$lev = $this->LevenshteinDistance($keywords, $word);
if ($lev == 0) {
$closest = $word;
$shortest = 0;
break;
}
if ($lev <= $shortest || $shortest < 0) {
$closest = $word;
$shortest = $lev;
}
}
if ($shortest == 0) {
$result = '';
} else {
$result = $closest;
}
return view('posts/search', compact('result'));
}
return redirect()->route('latestposts');
}
我是新手开发者,任何帮助表示赞赏。谢谢!
答案 0 :(得分:2)
这是一个很好的问题。为此,您需要单独处理输入字符串中的每个单词。这样,您可以使用字典中的单词替换输入字符串中的单个单词。
根据您的字典,您可能需要对每次点击进行进一步处理以防止误报。当我开始尝试您的代码时,仅使用Levenshtein距离时,输入中的大多数单词都被替换为“msn”。
我整理了一个测试用例,您可以从命令行运行以测试例程。除了单独处理每个单词以便我们可以进行替换之外,我将获得原始单词和词典单词的metaphone个键,然后使用similar_text来获得两者之间的相似性百分比。有一些阈值变量允许您设置Levenshtein距离的上限阈值,设置元电话密钥的长度限制,并设置元电话密钥相似度的最小百分比。
<?php
class Request
{
private $_data = [];
public function __construct(array $data = [])
{
$this->_data = $data;
}
public function input($key, $default = null)
{
return (array_key_exists($key, $this->_data)) ? $this->_data[$key] : $default;
}
}
function searchsuggestion(Request $request)
{
$allwords = array('facebook', 'orkut', 'twitter', 'yahoo', 'microsoft', 'paypal', 'google', 'bing', 'msn');
$keywords = trim($request->input('q'));
$levThreshold = 3;
$metaphoneLength = 5;
$metaphoneThreshold = 60;
if (!empty($keywords))
{
$keywordArr = explode(' ', $keywords);
$matchArr = [];
foreach ($keywordArr as $currKeyword)
{
$shortest = -1;
$closest = null;
foreach ($allwords as $word)
{
$lev = levenshtein($currKeyword, $word);
if ($lev == 0)
{
break;
}
if ($lev <= $shortest || $shortest < 0)
{
$closest = $word;
$shortest = $lev;
}
}
if (!empty($closest) && $shortest <= $levThreshold)
{
$origSoundex = metaphone($currKeyword, $metaphoneLength);
$foundSoundex = metaphone($closest, $metaphoneLength);
similar_text($origSoundex, $foundSoundex, $percentage);
if ($percentage > $metaphoneThreshold)
{
$matchArr[$currKeyword] = $closest;
}
}
}
if (!empty($matchArr))
{
$origWords = array_keys($matchArr);
$replaceWords = array_values($matchArr);
return str_replace($origWords, $replaceWords, $keywords);
}
return null;
//return view('posts/search', compact('result'));
}
//return redirect()->route('latestposts');
}
$request = new Request(['q' => 'How to use fasebuk and twitster?']);
$response = searchsuggestion($request);
print $response . "\n";