【问题标题】:Need a scalable way to Limit Content by using substr() and strpos() in PHP需要一种通过在 PHP 中使用 substr() 和 strpos() 来限制内容的可扩展方式
【发布时间】:2012-08-23 18:02:49
【问题描述】:

我正在使用 Markdown 在页面上呈现丰富的内容,使用 PHP。对于简短的版本,我认为可以将内容截断到第二段,或者从技术上讲,在两个 \r\n 交叉之后。所以我使用了这段代码:

substr($content, 0, strpos($content, "\r\n\r\n", strpos($content, "\r\n\r\n") + 1));

由于\r\n 的计数是硬编码的,并且也是以一种奇怪的方式计算的,(在第一个位置和其他东西之后使用 +1),我有没有更好的方法一个函数,它表示limitContent($content, $lines = 2) 并将行数传递给$lines 参数,默认情况下,它会截断为两行?

我当前的代码是:

/**
 * Break down the content of Markdown upto 2 breaks. 
 * @param string Markdown String
 * @return string Markdown String upto 2 breaks
 */
function limitContent($content)
{
    return substr($content, 0, strpos($content, "\r\n\r\n", strpos($content, "\r\n\r\n") + 1));
}

提前致谢。

【问题讨论】:

  • 嗯,Nin 和 Jack 都回答了我的问题,而且都很好。不能同时选择两个答案作为最佳答案! :P 现在帮我选一个! :)
  • 我们无法帮助您做出决定 :)
  • 嘿杰克,我可以使用 Nin 的代码,所以选择他的答案是最好的。但是已经给你们两个投了赞成票。这是我能做到的最好的! :)

标签: php string markdown substr strpos


【解决方案1】:

我对@9​​87654321@ 中两个选项之间的性能差异很感兴趣,因此我开始快速检查我手头的一些数据。我对 2 个字符串进行了测试:一个包含许多段落的长字符串和一个包含 2 个段落的长字符串。

Option 2 在第一个字符串上变成14 times faster,在第二个字符串上变成6% faster。所以这对第一个字符串有很大的优势。

此外,我将Praveen Kumar's 最初的想法变成了一个简单的基于循环的版本并进行了测试:

function limitContent($content, $lines=2) {
    $pos = -1;
    for ($i = 0; $i < $lines; $i++) {
        $pos = strpos($content, "\r\n\r\n", $pos+1);
        if ($pos === false) return $content;
    }
    return substr($content, 0, $pos);
}

这个版本原来是第一个字符串上的另一个178 times faster 和第二个字符串上的另一个25 times faster。虽然这些数字可能会根据数据和 php 版本对您有很大变化,但我认为它清楚地表明转换为数组并返回很慢。如果性能不是问题,我可能仍然会使用 Nin 的想法,因为它非常易于阅读。

【讨论】:

  • 哇...你已经完成了大量的测试。
  • @PraveenKumar 我会发表评论,但它有点长。但是,嘿评论帮助讽刺......这就是老兄的方法!
【解决方案2】:

您可以为此使用explode()

join("\r\n", array_slice(explode("\r\n\r\n", $content, $lines + 1), 0, $lines));

或者类似地,使用preg_split() - 来匹配LF和CRLF:

join("\r\n", array_slice(preg_split("/(?:\r?\n){2}/", $content, $lines), 0, $lines));

虽然上述解决方案的内存效率不是很高,因为最后一次匹配后的全部内容被复制到最后一个数组元素中。

您也可以使用strtok(),因为这可能更节省内存:

$result = '';
for ($i = 0, $tok = strtok($s, "\r\n\r\n"); false !== $tok && $i < $lines; ++$i, $tok = strtok("\r\n\r\n")) {
        $result .= $t . PHP_EOL;
}

【讨论】:

  • Nin 的帖子更好。但是让我知道哪个会消耗更少的内存?
  • @PraveenKumar 他/她的回答如何更好?我看到几乎相同的代码。
  • @Jack,唯一的区别是您需要从数组中删除最后一项。如果您真的不需要正则表达式,则不应使用 Preg_split。哪个,在这种情况下你不需要。
  • @Nin 但explode() 的限制为 2 最多只能给出 2 段,这应该与 OP 的 substr() 解决方案相同 ...
  • @nin preg_split() 解决方案的优点是同时匹配 LF 和 CRLF,而 explode() 只接受固定字符串。
【解决方案3】:

好吧,我误会了。这是你想要的吗?

function limitContent($content, $lines=2)
{
    $tmp=explode("\r\n\r\n", $content);
    $tmp=array_slice($tmp,0,$lines);
    return implode("\r\n", $tmp);
}

[编辑] 稍微好一点的是:

function limitContent($content, $lines=2)
    {
        $tmp=explode("\r\n\r\n", $content, $lines+1);
        unset($tmp[$lines]);
        return implode("\r\n", $tmp);
    }

【讨论】:

  • 你问错了。内容不能更改。我正在尝试获取内容,直到遇到第 n 个 \r\n
  • 这样可以作为单行脚本工作吗:return implode("\r\n", array_slice(explode("\r\n\r\n", $content), 0, $lines));
  • 是的,你可以在一行中完成,是的,应该是 \r\n\r\n
  • 在我上面一行说的代码中,应该是$lines还是$lines + 1
  • 只是线条,但您可以尝试一下,看看结果如何;)
猜你喜欢
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多