(PHP) 将用户搜索与数组匹配
(PHP) Matching a user search to an array
首先,我是开发新手,所以需要一点帮助。
我已经构建了一个简单的搜索字段(带有建议),并将用户发送到数组匹配的相关登陆页面。如果搜索不相关,我 return 会显示一条错误消息。但是,我的代码依赖于用户单击建议或在搜索字段中键入整个单词。因此,可用性较差。
下面的代码将突出显示我的问题。理想情况下,我需要将字段输入 'br' 与 'bristol' 匹配(根据我对用户的建议)。我认为解决方案是 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;
}
?>
这会让您更接近(如果不是)您的目标:
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");
}
}
可以优化,但一般来说:
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
中相同数量的起始字符进行比较
- 确保在 header 中使用
$county
而不是 $_GET["my_input"]
显然,如果用户输入 Be
,那么将选择第一个条目 Bedfordshire
。只要您的 "suggestions" 顺序相同,它就可以正常工作。
如果用户输入尾随 space 或其他内容,可能 trim()
:
if(substr($county, 0, strlen(trim($_GET["my_input"]))) == strtolower(trim($_GET["my_input"]))) {
您可以使用 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");
为您的代码实现 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
比 Bedfordshire
更接近 Bed
。
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;
首先,我是开发新手,所以需要一点帮助。
我已经构建了一个简单的搜索字段(带有建议),并将用户发送到数组匹配的相关登陆页面。如果搜索不相关,我 return 会显示一条错误消息。但是,我的代码依赖于用户单击建议或在搜索字段中键入整个单词。因此,可用性较差。
下面的代码将突出显示我的问题。理想情况下,我需要将字段输入 'br' 与 'bristol' 匹配(根据我对用户的建议)。我认为解决方案是 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;
}
?>
这会让您更接近(如果不是)您的目标:
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");
}
}
可以优化,但一般来说:
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
中相同数量的起始字符进行比较
- 确保在 header 中使用
$county
而不是$_GET["my_input"]
显然,如果用户输入 Be
,那么将选择第一个条目 Bedfordshire
。只要您的 "suggestions" 顺序相同,它就可以正常工作。
如果用户输入尾随 space 或其他内容,可能 trim()
:
if(substr($county, 0, strlen(trim($_GET["my_input"]))) == strtolower(trim($_GET["my_input"]))) {
您可以使用 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");
为您的代码实现 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
比 Bedfordshire
更接近 Bed
。
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;