фильтровать значения из массива, похожего на SQL, НАПРИМЕР ‘%search%’, используя PHP

#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']