我从网络服务中收集了一系列按字母顺序排序的街道名称。该数组存在于服务器端。
在客户端,用户开始输入他所居住的街道的名称,AJAX用于返回与部分街道名称最接近的匹配的列表,以及阵列中的下9个街道名称(列表)在他打字时更新。
例如,如果用户键入“al”,我希望结果如下:
这是我的尝试:
$matches = array();
for($i = 0; $i < count($streetNames); $i++)
{
if( (stripos($streetNames, $input) === 0 && count($matches) == 0) || count($matches) < 10 ){
$matches[] = $streetNames[$i];
} else {
break;
}
}
有没有其他人知道更快的方式?
请注意:我无法控制如何从数据库中获取此列表 - 它来自外部Web服务。
答案 0 :(得分:5)
使用preg_grep()
:
$matches = preg_grep('/al/', $streetNames);
注意:像你这样的方法将是一个强力搜索。如果你正在搜索一个巨大的名单(数十万)或搜索很多次,那么你可能需要更好的东西。对于小数据集,这很好。
答案 1 :(得分:4)
我认为你要找的是preg_grep()
您可以搜索以输入文本开头的元素:
$result = preg_grep('/^$input/', $streetNames);
或包含任何地方文字的元素:
$result = preg_grep('/$input/', $streetNames);
或者你也可以将搜索锚定到最后,但看起来不那么有用
答案 2 :(得分:4)
获得比查看所有字符串更快的唯一方法是为这种事物优化数据结构,trie。您可能无法控制Web服务为您提供的内容,但如果您可以将结果缓存在服务器上并重复使用它来处理许多请求,那么构建一个trie并使用它会更快。
答案 3 :(得分:4)
无法确定它是否更快,但这是我的版本。
$input = 'al';
$matches = array_filter($streetNames, create_function('$v','return (stripos($v,'.$input.') !== false ? true : false);'));
$weight = array_map(create_function('$v','return array($v,levenshtein('.$input.',$v));'),$matches);
uasort($weight, create_function('$a,$b', 'if ($a[1] == $b[1]) {return 0;} return ($a[1] < $b[1]) ? -1 : 1;'));
$weight = array_slice($weight, 0, 10);
这会创建一个加权的匹配列表。它们根据输入字符串和街道名称之间的距离进行排序。 0表示真正的匹配。
结果数组看起来像这样
array (
0 =>
array (
0 => 'Alola St',
1 => 7,
),
1 =>
array (
0 => 'Allen Rd',
1 => 7,
)
)
其中0 =&gt;街道名称和1 =&gt; levenshtein距离