#php #arrays
#php #массивы
Вопрос:
Я создал поле автозаполнения с помощью jQueryUI и сохранил свои данные в стандартном документе. Я могу считывать значения в массив… но я хотел бы иметь возможность возвращать совпадения по алфавиту на основе пользовательского ввода. Итак, если массив содержит [orange,blue,green,red,pink,brown,black]
и пользователь вводит bl, тогда я возвращаю только [blue,black]
.
Просматривая array_diff()
, но без полных совпадений по всему значению массива, я не уверен, как это использовать … может быть, добавлено регулярное выражение? Два моих самых слабых навыка манипулирование массивом и регулярное выражение Спасибо за помощь!
Комментарии:
1. вы смотрели на пример автозаполнения ‘xml-данные, проанализированные один раз’ ( jqueryui.com/demos/autocomplete/#xml )? Возможно, вам будет проще и эффективнее изменить формат хранения данных.
Ответ №1:
Вам не нужно использовать array_filter
и пользовательскую / лямбда-функцию, preg_grep
которая делает свое дело:
$input = preg_quote('bl', '~'); // don't forget to quote input string!
$data = array('orange', 'blue', 'green', 'red', 'pink', 'brown', 'black');
$result = preg_grep('~' . $input . '~', $data);
Комментарии:
1. Ваш ответ привел меня к
preg_grep()
. Изменилpreg_filter()
на это и удалилnull
, и все работало как по маслу; спасибо!2. @Ecropolis: Я думаю, что правильный синтаксис в данном случае —
preg_filter('~' . $input . '~', '$0', $data);
.3. @EmilioGort: Конечно, просто добавьте
i
модификатор после последнего~
разделителя.4. @MichaelRopy @Майклропи:
$result = preg_grep('~^' . $input . '~', $data);
5. Отличный ответ. Каждый раз, когда этот ответ появляется в Google, когда я ищу фильтры массива.
Ответ №2:
array_filter()
, с функцией фильтрации обратного вызова, основанной на stripos()
, должно сработать.
Например, если входные данные хранятся в $input
, а ваш массив в $data
:
$input = 'bl';
$data = array('orange', 'blue', 'green', 'red', 'pink', 'brown', 'black');
Фильтрация для сохранения только тех слов, которые содержат $input
(независимо от того, где в строке), может быть выполнена следующим образом :
$result = array_filter($data, function ($item) use ($input) {
if (stripos($item, $input) !== false) {
return true;
}
return false;
});
var_dump($result);
И здесь вы получите :
array
1 => string 'blue' (length=4)
6 => string 'black' (length=5)
Изменяя обратный вызов фильтрации, вы можете :
- Проверить, начинается ли строка с ввода — проверка, является ли значение, возвращаемое
stripos()
=== 0
- Используйте функцию сопоставления с учетом регистра, например
strpos()
Комментарии:
1. это правильное решение, если вы хотите сохранить значения ключей и иметь возможность использовать нецелочисленные ключи
Ответ №3:
Вы могли бы просто выполнить итерацию по массиву, чтобы найти все строки, которые начинаются с заданных букв. Наличие списка слов, уже отсортированных в вашем плоском файле, вероятно, ускорило бы процесс. Я думаю, что это работает довольно хорошо:
$input = strtolower("bl"); //from the user
$colors = array("black", "blue", "brown", "..."); //already sorted alphabetically
$matches = array();
foreach ($colors as $c){
if (strpos($c, $input) === 0){
//if $c starts with $input, add to matches list
$matches[] = $c;
} else if (strcmp($input, $c) < 0){
//$input comes after $c in alpha order
//since $colors is sorted, we know that we won't find any more matches
break;
}
}
Ответ №4:
как %search%
function like(array $arr, string $patron): array
{
return array_filter($arr, static function (mixed $value) use ($patron): bool {
return 1 === preg_match(sprintf('/^%s$/i', preg_replace('/(^%)|(%$)/', '.*', $patron)), $value);
});
}
тест
$b=['a'=>'peter','b'=>'patter','c'=>'alter','d'=>'all'];
var_dump(like($b,'%ter'));// ['a'=>'peter','b'=>'patter','c'=>'alter']
var_dump(like($b,'al%'));//['c'=>'alter','d'=>'all']