【问题标题】:PHP Check if an array of strings contains any value from an array of substringsPHP 检查字符串数组是否包含子字符串数组中的任何值
【发布时间】:2022-01-07 15:58:28
【问题描述】:

例如。我有 2 个数组:

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

我想检查$arr1 的两个值是否作为子字符串存在于$arr2 中。 $arr2 也可能有其他元素,但它是否包含 $arr1 的所有索引作为子字符串并不重要。

我知道标准的嵌套循环方法,但我不想使用它,因为性能会很糟糕(因为我有一个大数组)。我想问一下 PHP 是否包含为此的内置函数,或者是否有另一种方法可以以更好的时间复杂度完成此任务 [最好是 O(log n),但 O(n) 也可以]。

【问题讨论】:

  • 您提供的样本数据的答案应该是什么,因为makemaker 中,但这算不算
  • 您是否对嵌套循环进行了实际性能测试,以确认性能确实很糟糕?
  • @RiggsFolly 是的,它很重要,因为makemaker 的子字符串,而cakebirthday cake 的子字符串,所以它应该返回true。
  • @ChrisHaas 我在实际情况中使用了嵌套循环代码,是的,当我有可以匹配一个巨大号的数组时。其他数组,性能很差。
  • 我认为没有任何内置的 PHP 函数可以实现这一点,因此需要嵌套循环。确保在找到匹配项时跳出内部循环,这将提高效率。

标签: php arrays


【解决方案1】:

如果你说你有一个大数组要检查,优化数组的处理。

  1. 一旦你在 arr1 中找不到一项,它就会全部终止并返回 false
  2. 通过引用传递数组参数,因此无需将数组复制到堆栈中
  3. 将最有可能在 arr2 中找不到的东西放在 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';
}

【讨论】:

  • 谢谢,这绝对有帮助
【解决方案2】:

我认为嵌套循环是唯一的方法,但为了更有效地在答案确定后立即跳出循环。

$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";

【讨论】:

    【解决方案3】:

    如果我们制作第二个数组的字符串

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

    然后使用 array_filter 如下:

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

    这里我们有来自 $arr1 的所有匹配子字符串。

    【讨论】:

    • 我已经用特殊字符对 $arr2 进行了内爆,该字符不会被搜索到,只是为了使搜索更快并保持元素分离。
    • 这对我不起作用 :( 顺便说一句,这与具有指数时间复杂度的嵌套循环不是一回事吗?
    • 这将为给定的输入返回一个空数组。
    • 您正在寻找整个匹配项,而不是子字符串。
    猜你喜欢
    • 2012-04-30
    • 2021-12-14
    • 2015-09-08
    • 2015-02-28
    • 2020-12-01
    • 1970-01-01
    • 2013-11-12
    • 1970-01-01
    相关资源
    最近更新 更多