我认为这将是最有效/最简单的解决方案(但是我没有通过一些运行时测试运行它)。
function str_replace_except_last($needle, $replace, $text) {
if ($last_pos = strrpos($text, $needle)) {
$text = str_replace($needle, $replace, substr($text, 0, $last_pos)) . substr($text, $last_pos);
}
return $text;
}
由于问题也与效率有关,我决定测试两个版本(我的版本和@Don'tPanic 提供的版本,它基于数组)。
首先 - 我只想说过早的优化是万恶之源
现在我们已经完成了,我们可以下一步了:)
我决定创建一个 10M 字符的随机字符串,该字符串还将包含 .(这将是我们的针)。
我在同一个字符串上运行这两个函数 1000 次,并检查了每个函数运行的平均时间。
我还检查了每个函数需要多少内存才能工作。
结果如下:
- 10M 字符串的创建耗时 2.3 秒。
- 字符串函数平均运行 0.016 秒(每次迭代)
内存使用量为 9.8M
- 数组函数平均运行 0.049 秒(每次迭代)
内存使用量为 45.1M
这是完整的代码(如果你想自己运行的话):
$ITERATIONS = 1000;
function generateRandomString($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
function func_str($needle, $replace, $text) {
$m1 = memory_get_usage();
if ($last_pos = strrpos($text, $needle)) {
$text = str_replace($needle, $replace, substr($text, 0, $last_pos)) . substr($text, $last_pos);
}
$m2 = memory_get_usage();
//echo "memory diff ". ($m2-$m1) ."\n";
return $text;
}
function func_arr($needle, $replace, $text) {
$m1 = memory_get_usage();
$array = explode($replace, $text, substr_count($text, $replace));
$text = implode($replacement, $array);
$m2 = memory_get_usage();
//echo "memory diff ". ($m2-$m1) ."\n";
return $text;
}
$m1 = memory_get_usage();
$s = microtime(true);
$str1 = generateRandomString(10000000);
$e = microtime(true);
echo "create took ". ($e-$s) ." seconds\n";
echo "Number of occurances: " . substr_count($str1, '.') . "\n";
$s = microtime(true);
for ($i = 0; $i < $ITERATIONS; $i++) {
func_str(".","",$str1);
}
$e = microtime(true);
echo "remove took ". ($e-$s) ." seconds, avg: ". ($e-$s)/$ITERATIONS ."\n";
$s = microtime(true);
for ($i = 0; $i < $ITERATIONS; $i++) {
func_arr(".","",$str1);
}
$e = microtime(true);
echo "remove took ". ($e-$s) ." seconds, avg: ". ($e-$s)/$ITERATIONS ."\n";
(我把函数内部内存使用的输出注释掉了,如果你想要的话可以去掉注释)。