I want to return array that does not contains a list of characters.
Below code works fine for one keyword ('bc'
).
$array = array("abc", "def", "ghi");
$filterArray = array_filter($array, function ($var) {return(strpos($var, 'bc') === false);});
print_r($filterArray);
However, below code does not work when I try to filter out multiple keywords by using $excludeKeyword_arr
and 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);
It should be return array instead of boolean type.
There are 2 problems with the code. The first is that the scope of $exclude
doesn't allow the closure to access it, simply solved by passing it in with use
.
The second problem is that you always filter the original array ($array
) and so the accumulative effect isn't achieved. So here I copy the array and keep on filtering the copy ($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);
which results in
Array
(
[2] => ghi
)
You can use preg_grep which will do the opposite and match the ones that has bc
or de
then 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
For best performance, use a foreach()
loop with a conditional break
-- this way php doesn't need to perform useless iterations.
If the substring is found anywhere in the haystack string, remove it from the array of haystacks using unset()
.
Code: (Demo)
$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));
Output:
array (
0 => 'ghi',
)
A word of caution: if entertaining the notion of a preg_
call for brevity's sake, understand that for reliability/stability, you must apply preg_quote()
to each values in the needles array if there is any chance of characters with special meaning to the regex engine.
I would do the same as @Andreas, but reindexing in the end.
$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));
Demo
Read more:
Pipe ( ab|de ) = https://www.regular-expressions.info/alternation.html