Несколько array_filter и strpos

Я хочу вернуть массив, который не содержит списка символов.

Код ниже отлично работает для одного ключевого слова ('bc').

$array = array("abc", "def", "ghi");
$filterArray = array_filter($array, function ($var) {return(strpos($var, 'bc') === false);});
print_r($filterArray);

Однако приведенный ниже код не работает, когда я пытаюсь отфильтровать несколько ключевых слов с помощью $excludeKeyword_arr и foreach.

$array = array("abc", "def", "ghi");
$excludeKeyword_arr = ("ab", "de");
foreach($excludeKeyword_arr as $exclude){
    $filterArray = array_filter($array, function ($var) {return(strpos($var, $exclude) === false);});
}
print_r($filterArray);

Это должен быть возвращаемый массив вместо логического типа.


person Jace    schedule 05.01.2019    source источник
comment
stackoverflow.com/questions/10589921/   -  person Abdur Rahman    schedule 05.01.2019


Ответы (4)


Есть 2 проблемы с кодом. Во-первых, область действия $exclude не позволяет закрытию получить к нему доступ, что просто решается путем передачи его с помощью use.

Вторая проблема заключается в том, что вы всегда фильтруете исходный массив ($array), поэтому накопительный эффект не достигается. Итак, здесь я копирую массив и продолжаю фильтровать копию ($filterArray = array_filter($filterArray, function)...

$array = array("abc", "def", "ghi");
$excludeKeyword_arr = array("ab", "de");
$filterArray = $array;
foreach($excludeKeyword_arr as $exclude){
    $filterArray = array_filter($filterArray, function ($var) use ($exclude) 
                     {return(strpos($var, $exclude) === false);});
}
print_r($filterArray);

что приводит к

Array
(
    [2] => ghi
)
person Nigel Ren    schedule 05.01.2019

Вы можете использовать preg_grep, который сделает обратное и будет соответствовать тем, у которых есть bc или de, а затем array_diff.

$array = array("abc", "def", "ghi");
$excludeKeyword_arr = array("bc", "de");
$exclude_values = preg_grep("/". implode("|", $excludeKeyword_arr) . "/", $array);
$filterArray = array_diff($array, $values_with_bc);

print_r($filterArray); // [ 2 => "ghi"]

https://3v4l.org/IpNal

person Andreas    schedule 05.01.2019
comment
Вам нужно изменить $values_with_bc, а также обновить те, у которых есть bc или de, затем - person Nigel Ren; 05.01.2019

Для лучшей производительности используйте цикл foreach() с условным break — таким образом php не нужно выполнять бесполезные итерации.

Если подстрока найдена где-либо в строке стога сена, удалите ее из массива стога сена с помощью unset().

Код: (Демо)

$array = ["abc", "def", "ghi"];
$excludeKeyword_arr = ["ab", "de"];

foreach ($array as $index => $haystack) {
    foreach ($excludeKeyword_arr as $needle) {
        if (strpos($haystack, $needle) !== false) {
            unset($array[$index]);
            break;
        }
    }
}
var_export(array_values($array));

Выход:

array (
  0 => 'ghi',
)

Небольшое предостережение: если для краткости рассматривать понятие вызова preg_, имейте в виду, что для надежности/стабильности вы должны применять preg_quote() к каждому значению в массиве игл, если есть вероятность наличия символов со специальным значением для механизма регулярных выражений.

person mickmackusa    schedule 28.01.2020

Я бы сделал то же самое, что и @Andreas, но в конце переиндексировал.

$array           = ["ab", "def", "ghi"];
$excludeKeywords = ["ab", "de"];

$pattern = implode("|", $excludeKeywords);
$result = preg_grep("/$pattern/i", $array);

// Positive (Reindex)
print_r(array_values($result));

// Negative (Reindex)
$result = array_diff($array, $result);
print_r(array_values($result));

Демо

Прочитайте больше:

Канал ( ab|de ) = https://www.regular-expressions.info/alternation.html


person Jeff.Dev    schedule 09.02.2020