(PHP)将用户搜索与数组匹配

时间:2016-06-13 20:36:21

标签: php search levenshtein-distance

首先,我是开发新手,所以需要一点手握。

我已经构建了一个简单的搜索字段(包含建议),并将用户发送到阵列匹配的相关登录页面。如果搜索不相关,我会返回错误消息。但是,我的代码依赖于用户单击建议或在搜索字段中键入整个单词。因此,可用性很差。

以下代码将突出显示我的问题。理想情况下,我需要匹配字段输入' br'到布里斯托尔' (根据我对用户的建议)。我认为解决方案是http://php.net/manual/en/function.levenshtein.php,但我在实施方面遇到了问题(就像我说的,我是新的)。我很感激任何指导。

非常感谢您的时间!

<?php

$counties = array("Avon",
"Bristol",
"Bedfordshire",
"Berkshire",
"Buckinghamshire"
);

if (in_array(strtolower($_GET["my_input"]), array_map('strtolower', $counties)))

{ header('Location: http://domain.co.uk/county/'.strtolower(str_replace(' ', '-', $_GET['my_input'])));
}

else

{
header('Location: ' . $_SERVER['HTTP_REFERER'] . "?message=tryagain");
exit;
}

?>

4 个答案:

答案 0 :(得分:0)

这可以让你更接近(如果没有)你的目标:

if(array_key_exists('my_input', $_GET){

   $input = $_GET["my_input"];
   $counties = array("Avon", "Bristol", "Bedfordshire", "Berkshire",  "Buckinghamshire");

   // no shortest distance found, yet
   $shortest = -1;

   // loop through words to find the closest
   foreach ($counties as $country) {

      $lev = levenshtein($input, $country);

      // check for an exact match
      if ($lev == 0) {
          $closest = $country;
          $shortest = 0;
          // break out of the loop; we've found an exact match
          break;
     }

       // if this distance is less than the next found shortest
       // distance, OR if a next shortest word has not yet been found
       if ($lev <= $shortest || $shortest < 0) {
           // set the closest match, and shortest distance
           $closest  = $country;
           $shortest = $lev;
       }
   }

    if($shortest < 5){ //insert your own value here ( accuracy )
        header('Location: http://domain.co.uk/county/'.strtolower($closest));
    }else{    
        // if not match
        header('Location: ' . $_SERVER['HTTP_REFERER'] . "?message=tryagain");
    }

}

答案 1 :(得分:0)

可以进行优化,但一般情况下:

foreach(array_map('strtolower', $counties) as $county) {
    if(substr($county, 0, strlen($_GET["my_input"])) == strtolower($_GET["my_input"])) {
        header('Location: http://domain.co.uk/county/'.str_replace(' ', '-', $county));
        exit;
    }
}
header('Location: ' . $_SERVER['HTTP_REFERER'] . "?message=tryagain");
exit;
  • 循环$counties并将$_GET["my_input"]$county
  • 中相同数量的起始字符进行比较
  • 请务必在标题中使用$county而不是$_GET["my_input"]

显然,如果用户输入Be,则会选择Bedfordshire作为第一个条目。只要你的建议&#34;按照相同的顺序它应该可以正常工作。

如果用户输入尾随空格或某些内容,可能是trim()

if(substr($county, 0, strlen(trim($_GET["my_input"]))) == strtolower(trim($_GET["my_input"]))) {

答案 2 :(得分:0)

如果找到匹配项,您可以使用startsWith function from this answer并遍历您的县设置标记。

<?php

function startsWith($haystack, $needle) {
    // search backwards starting from haystack length characters from the end
    return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false;
}

$counties = array("Avon",
"Bristol",
"Bedfordshire",
"Berkshire",
"Buckinghamshire"
);

foreach (array_map('strtolower', $counties) as $county){
  if(startsWith($county, strtolower($_GET["my_input"]))){
    header('Location: http://domain.co.uk/county/'.strtolower(str_replace(' ', '-', $_GET['my_input'])));
    $match = true;
    break;
  }
}

if(empty($match))
  header('Location: ' . $_SERVER['HTTP_REFERER'] . "?message=tryagain");

答案 3 :(得分:0)

为您的代码实现levenshtein看起来像:

$counties = array(
    "Avon",
    "Bristol",
    "Bedfordshire",
    "Berkshire",
    "Buckinghamshire"
);

$input = 'Bed';
$shortest = -1;

foreach($counties as $county) {

    $lev = levenshtein($input, $county);
    var_dump($county, $lev);

    if ($lev == 0) {
        $closest = $county;
        break;
    }

    if ($lev <= $shortest || $shortest < 0) {
        $closest  = $county;
        $shortest = $lev;
    }

}

echo $closest;

但我认为这不会完全符合您的要求,因为技术上Avon使用此算法的距离比Bed更接近Bedfordshire

PHP中有一个similar_text函数,可以为您提供更好的结果。

$counties = array(
    "Avon",
    "Bristol",
    "Bedfordshire",
    "Berkshire",
    "Buckinghamshire"
);

$input = 'Bed';
$mostSimilar = 0;

foreach($counties as $county) {

    similar_text($input, $county, $similarity);

    if ($similarity == 100) {
        $closest = $county;
        break;
    }

    if ($mostSimilar <= $similarity || $similarity < 0) {
        $closest  = $county;
        $mostSimilar = $similarity;
    }

}

echo $closest;