简体   繁体   中英

PHP Check if an array of strings contains any value from an array of substrings

For eg. I have 2 arrays:

$arr1 = array("cake", "make"); and $arr2 = array("birthday cake", "maker", "a random index");

I want to check if both the values of $arr1 exist in $arr2 as a substring. $arr2 may also have other elements, but it doesn't matter if it contains all the indexes of $arr1 as substrings.

I know the standard nested-loop approach to this but I don't want to use it as the performance will be terrible (as I have got a large array). I wanted to ask if PHP contains a built in function for this, or if there is an alternative method to accomplish this with a better time complexity [ preferrably O(log n), but O(n) will do as well ].

If as you say you have a large array to check, optimize the processing of the arrays.

  1. As soon as you fail to find one of the items in arr1, its all over terminate and return false
  2. Pass the array parameters by reference, so no copying the arrays to the stack
  3. Put the most likely thing NOT to be found in arr2 at the beginning of arr1
$arr1 = array( "cake", "make");
$arr2 = array("birthday cake", "maker", "a random index");

// pass arrays by reference, so you dont have to create copies 
// of large arrays on to the stack
function testThem(&$arr1, &$arr2) {
    // as soon as a unfound situation is indicated, return from the function with false
    foreach ($arr1 as $a1) {
        $found = false;
        foreach ($arr2 as $a2) {
            if (strpos($a2, $a1) !== false) {
                //as soon as a found occurs break out of this foreach
                $found = true;
                break;
            }
        }
        // If we get here with a $found still = false
        // we didnt find one of the things in $arr1 within $arr2 
        // so no more looping required. Finish and return false
        if (!$found) { 
            return false;
        }
    }    
    // only if we find all the items do we eventually get here after lots of loops
    return true;
}


if ( testThem($arr1, $arr2) ) {
    echo 'All Found';
} else {
    echo 'Something not found';
}

If we make the string of the second array

$arr2 = implode('###',$arr2);

and then use array_filter as below:

$result = array_filter($arr1,function($value) use($arr2){
    return (strpos($value,$arr2)!==false)?$value:false;
});

print_r(array_filter($result));

Here we have all the matching sub-strings from $arr1.

I think nested loops are the only way, but to make it more efficient break out of the loops as soon as the answer is determined.

$found_all = true;
foreach ($arr1 as $str1) {
    $found1 = false;
    foreach ($arr2 as $str2) {
        if (strpos($str2, $str1) !== false) {
            $found1 = true;
            break;
        }
    }
    if (!$found1) {
        $found_all = false;
        break;
    }
}
echo $found_all ? "All found" : "Not all found";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM