У меня есть массив названий улицы, отсортированных в алфавитном порядке, что я собрался из веб-сервиса. Этот массив существует на стороне сервера.
На стороне клиента пользователь начинает вводить имя улицы, на которой он живет, и 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;
}
}
Кто-либо еще знает более быстрый путь?
Пожалуйста, примите во внимание: Я не имею никакого контроля над тем, как этот список получен из базы данных - это от внешнего веб-сервиса.
единственный способ получить быстрее, чем просматривать все строки, будет иметь структуру данных, оптимизированную для такого рода вещи, TRIE . Возможно, у вас может быть не контролирует то, что WebService дает вам, но если вы сможете кэшировать результат на вашем сервере и повторно использовать его для обслуживания многих запросов, затем построение TRIE и использование, которое будет намного быстрее.
Не может действительно сказать, если это быстрее, но это моя версия из этого.
$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 => имя улицы и 1 => Расстояние Левенштейна
Я думаю, что вы ищете PREG_GREP ()
. Вы можете искать либо для элементов, начиная с входного текста:
$result = preg_grep('/^$input/', $streetNames);
или для элементов, которые содержат текст в любом месте:
$result = preg_grep('/$input/', $streetNames);
Или вы также можете закрепить поиск до конца, но это не выглядит так полезно
Используйте preg_grep()
:
$matches = preg_grep('/al/', $streetNames);
Примечание: этот метод, как и ваш, будет выполнять поиск методом грубой силы. Если вы ищете в огромном списке имен (сотни тысяч) или ищете огромное количество раз, то вам может понадобиться что-то получше. Однако для небольших наборов данных это нормально.