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

时间:2012-07-17 10:47:23

标签: php loops str-replace strpos

我有一个循环,它在每次迭代中占用大量文本,并用一些其他内容替换特定的占位符('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字段类型)?

3 个答案:

答案 0 :(得分:4)

解决您的问题

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

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

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

您当前的问题不是简单的代码审查,而是一个方法问题。您已经将小型数据集的典型技术用作处理大型数据集的方法。如果您有中等数据集并且感觉不到性能衰减,那么“将foreach包装在简单脚本上”的概念就有效,如果您不需要单独的方法来处理大型数据集。

回答你的问题

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

如果干草堆不包含针,strpos === str_replace(在计算复杂性方面),因为它们都必须穿过整个字符串直到最后才能确保没有针。

对于任何不包含针头的干草堆而言,使用这两种功能会增加100%的计算复杂度,并且对于包含针头的任何干草堆而言,计算复杂性会增加1%到100%,因为strpos在找到第一根针后会立即返回,这可以在弦的开头,中间或末尾找到。

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

答案 1 :(得分:0)

感谢Mihai - 这很有意义 - 但是在这个特殊场景中,即使我首先从数据库中获取所有记录 - 意味着所有具有相关类别的图像 - $ string会很少包含的不仅仅是一两个令牌' - 意味着如果有许多类别('令牌')进行比较,使用strpos()实际上可以节省时间。

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

因此,如果假设有大量的“令牌”,那么您的建议就会奏效。在$ string中找到的比较我们正在循环的类别数量,但是对于少量的标记'我认为strpos()仍然是有益的,因为这将是每个类别执行的唯一一个而不是当strpos()返回true时跟随两个 - 在这种情况下它是以strpos形式支付的小代价()每次在循环中比较ob和str_replace - 你认为不是吗?

我非常感谢你的解释。

答案 2 :(得分:0)

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