Multiple array_filter and strpos

北城以北 提交于 2020-01-30 11:40:09

问题


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.


回答1:


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
)



回答2:


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




回答3:


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.



来源:https://stackoverflow.com/questions/54050305/multiple-array-filter-and-strpos

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!