PHP在str_replace()之前使用strpos()


PHP using strpos() before str_replace()

我有一个循环,它在每次迭代中都会获取大量文本,并用其他内容替换特定的占位符("token"),比如:

$string = $pageContent;
foreach($categories as $row) {
    $images = $mdlGallery->getByCategory($row['id']);
    if (!empty($images)) {
        $plug = Plugin::get('includes/gallery', array('rows' => $images));
        $string = str_replace($row['token'], $plug, $string);
    }
}

Plugin类及其get()方法只需从特定目录中获取正确的文件,并将缓冲区输出为字符串。

可能有大量的类别,因此我想知道在使用strpos()函数填充给定类别中的所有图像之前,是否最好先检查输入字符串中是否出现了特定的"标记":

foreach($categories as $row) {
    if (strpos($string, $row['token']) !== false) {
        $images = $mdlGallery->getByCategory($row['id']);
        if (!empty($images)) {
            $plug = Plugin::get('includes/gallery', array('rows' => $images));
            $string = str_replace($row['token'], $plug, $string);
        }
    }
}

我关心的是表演-这会有帮助吗?-考虑$string可能包含大量字符(MySQL中的TEXT字段类型)?

解决您的问题

根据您的示例代码,Plugin::get()中使用的文件似乎很小,这意味着包含或读取它们不会产生很大的性能成本,但如果有很多文件,您可能需要考虑这些成本,因为操作系统排队机制,即使它们包含的数据不多。

getByCategory方法应该会产生巨大的性能成本,因为它意味着许多连接->查询->读取->关闭数据库的通信序列,并且每个序列都意味着大量数据的传输(您提到的TEXT字段)。

您应该考虑使用一个SQL查询将数据作为批处理操作获取,并将其存储在按行id索引的缓存变量中,以便getByCategory可以从缓存中获取数据。

您当前的问题不是简单的代码审查问题,而是方法问题。您使用了一种针对小型数据集的典型技术作为处理大型数据集的方法。如果你有中等规模的数据集,并且没有感觉到性能下降,那么"在简单脚本上覆盖前臂"的概念就有效了,如果你没有,那么你需要一种单独的方法来处理大型数据集。

回答您的问题

使用strpos意味着在整个干草堆中运行一次,检查它是否包含针头,然后再次运行,用str_replace进行更换。

如果干草堆不包含针头,strpos === str_replace(在计算复杂度方面),因为它们都必须穿过整个绳子直到最后,以确保没有针头。

使用这两个函数会为任何不包含针的草垛增加100%的计算复杂度,并为任何包含针的草垛增加1%至100%的计算复杂性,因为strpos将在找到的第一个针之后立即返回,该针可以在字符串的开头、中间或结尾找到。

简而言之,不要使用strpos,这对您没有帮助,如果您使用preg_replace,对于不包含针的干草堆,RegEx引擎可能会比strpos产生更大的计算复杂性。

谢谢Mihai-这很有意义,然而,在这种特殊的情况下,即使我首先从数据库中获取所有记录,也就是说,所有图像都有关联的类别,$字符串很少只包含一个或两个以上的"标记",这意味着如果有许多类别("标记")可供比较,使用strpos()实际上可以节省时间。

想象一下,我们没有在每次迭代中调用getByCategory,因为我们已经将所有可能的记录存储在早期生成的数组中——我们仍然需要在Plugin::get()方法和str_replace()中进行输出缓冲——这意味着如果我们有20个类别——这将发生20次,而$string中不一定包含"token"。

因此,如果假设在$字符串中发现了大量的"令牌",与我们正在循环的类别数量相比,你的建议会奏效,但对于少量的"token",我认为strpos()仍然是有益的,因为这将是每个类别唯一执行的一个,而不是当strpos)返回true时执行的两个-在这种情况下,与循环中每次ob和str_replace一起相比,以strpos的形式付出的代价很小-你不认为吗?

不过我非常感谢你的解释。

如果您正在寻找优化(尤其是微观优化),我认为最好自己进行基准测试。任何实现都有不止一个变体(通常),因此最好对您使用的变体进行基准测试。根据这一点,您可以在此处看到基准测试结果:带有strpos:http://3v4l.org/pb4hY#v533不带strpos:http://3v4l.org/v35gT