假设我们有一个非常大的字符串$str
,我们需要将一小部分字符串(假设整个字符串,但没有前3个字节)传递给函数。使用substr
:
consumer_function(substr($str, 3));
似乎效率不高,因为substr
似乎在返回结果之前将字符从初始字符串复制到新字符串中。有没有办法我们可以将该字符串的大部分传递给函数而无需过多的复制?我们无法更改该函数的代码。
答案 0 :(得分:3)
我不认为这里有问题。你猜测存在问题,你没有理由认为存在问题。
“看起来效率不高”不是问题。如果你测量它并发现它很慢,那你就有问题了。然后,在代码上使用XDebug之类的分析器,看看是否可以找到代码的哪些部分很慢。
如果你没有问题,那么就无法解决问题,并且猜测可能看起来可能很慢的东西并不意味着你有问题。
优化俱乐部的规则:
答案 1 :(得分:1)
使用$str
并且无需创建另一个变量即可:
for($i=1;$i<=$no;$i++) $str[strlen($str)-$i]=null;
$str=rtrim($str);
从结尾处删除最后$no
个字符
还有:
for($i=0;$i<$no;$i++) $str[$i]=null;
$str=ltrim($str);
从中刮掉第一个字符。
测试A:从字符串开头削减30个字符
测试用例1: substr($ str,30)
52784749 bytes of data
0.72129082679749s execution time
52903844 bytes of ram used
测试用例2:循环,使用空字符串字符和ltrim
52784749 bytes of data
0.23676204681396s execution time
52904276 bytes of ram used
测试B:从字符串末尾削减30个字符
测试用例1: substr($ str,0,-30)
52784749 bytes of data
0.83467292785645s execution time
52903924 bytes of ram used
测试用例2:循环,使用空字符串字符和rtrim
52784749 bytes of data
0.27498316764832s execution time
52904340 bytes of ram used
当您真正需要这种微优化时,这是一个合理的问题,使用此解决方案实现 3x 更好的处理时间,甚至更好(最多40x ),数据集较小,为1.2Mb 需要更多测试,但看起来是一个可行的选择。
正如格里戈里指出的那样,记忆在速度上是一个很大的问题,而弗格斯注意到ltrim()的记忆足迹:
不幸的是,使用trim()会让我们回到原点,在某个时刻使用两倍的内存并且只有速度增加。
另一方面,如果不使用trim(),我们最终会得到一个长度相同且 null字符的字符串,但速度增加和记忆保护。
也适用于 null , false 和“ \ x08 ”(BackSpace chr)。
var_dump()将字符串报告为与原始字符串相同的长度,但引号中的值是您所期望的:只有您感兴趣的部分。
问题太糟糕了[关闭] :(
答案 2 :(得分:1)
'让它发挥作用,然后让它变得完美'
严重 - 过早优化并不是一条很好的路线。除非你觉得肯定有性能损失 - 一个明显的命中 - 然后离开它。使用一些很少使用的技巧来做一些非常常见的事情只会在你重新访问时引起维护噩梦。
默认情况下没有其他可用的方法 - 如果您在PHP网站上查看String Functions,您可以看到可用的内容。
但是,您可以使用数组表示法来处理字符串:
$str[ index ]
例如:
$str = "abc";
$str[0] // a
$str[1] // b
$str[2] // c
结合unset()
,完全可以手动取消字符串中的特定项目..
$str = "abc";
unset( $str[1] ); // $str = "ac" now.
投入基本循环,可以使用;在你的例子中你想删除3 - 所以你会这样做:(注意,数组符号=索引从0开始!!)
for( $i=0; $i<=2; $i++ )
unset( $str[i] );
但是,请记住您丢失了原始字符串 - 以后您可能需要的任何数据?是的,它消失了。
然而 - 如果我是你,我会坚持使用substr()
。
编辑:Grigory在评论中指出,这在PHP 5.3中不起作用 - 这与PHP documentation states一样奇怪:
按字符串访问和修改字符串
可以通过使用方形数组括号在字符串后面指定所需字符的从零开始的偏移来访问和修改字符串中的字符,如$ str [42]。将字符串视为用于此目的的字符数组。当您想要提取或替换多个字符时,可以使用函数substr()和substr_replace()。
所以这是坚持substr()
的另一个原因 - 我现在有点好奇;所以我将尝试看看这种行为是否仅由于unset()
而发生。会报告回来!
更新:正如预期的那样,此行为归因于unset()
- 我不能说实际上我太惊讶了。
**Fatal errors:** [type:1] -- Cannot unset string offsets -- at line 7
您可以在此处phpFiddle查看我的测试用例。
所以总的来说,没有字符串函数可以在语言中内置本地,而你不能通过逐个字符来操作字符串。坚持推荐的方式。
答案 3 :(得分:0)
基于之前的答案。如果我们可以相信php会尝试像数组一样的字符串,也就是说,没有内部重复,这里有两个更多的解决方案来测试。请注意,我们多次重写原始字符串$str
。
$str = "abcdefghi"; // a given string
$set_strip = 3; // how many chars strip
$strlen = strlen($str);
$strip = $strlen - $set_strip;
// test before commit errors
if ($strip > 0 && $strip <= $strlen)
{
// SOL. 1.- using str_split with $strip as 2º parameter (trusting strrev() acts efficienly)
$str = strrev($str); // reverse string
$str = str_split($str, $strip); // split into a array with 2 elements
$str = strrev($str[0]); // back to original order
// SOL. 2.- shortening array $set_strip times
$str = str_split($str);
for ($i = 0; $i < $set_strip; $i ++ )
array_shift($str);
$str = implode('', $str); // back to string
}
else
echo "\$set_strip value not allowed = $set_strip, must be non-negative and < $strlen";
两者都给我们字符串:defghi