Chr*_*ris 68 php string concatenation
在Java和C#等语言中,字符串是不可变的,并且一次构建一个字符串可能在计算上很昂贵.在所述语言中,有一些库类可以降低这种成本,例如C#System.Text.StringBuilder和Java java.lang.StringBuilder.
php(4或5;我对两者都感兴趣)是否共享此限制?如果是这样,是否有类似的解决方案可用?
Pet*_*ley 60
不,PHP中没有stringbuilder类的类型,因为字符串是可变的.
话虽如此,根据你正在做的事情,有不同的方法来建立一个字符串.
例如,echo将接受逗号分隔的标记以进行输出.
// This...
echo 'one', 'two';
// Is the same as this
echo 'one';
echo 'two';
Run Code Online (Sandbox Code Playgroud)
这意味着您可以输出复杂的字符串而不实际使用连接,这会更慢
// This...
echo 'one', 'two';
// Is faster than this...
echo 'one' . 'two';
Run Code Online (Sandbox Code Playgroud)
如果需要在变量中捕获此输出,则可以使用输出缓冲功能执行此操作.
此外,PHP的阵列性能非常好.如果你想做一个逗号分隔的值列表,只需使用implode()
$values = array( 'one', 'two', 'three' );
$valueList = implode( ', ', $values );
Run Code Online (Sandbox Code Playgroud)
最后,确保您熟悉PHP的字符串类型,它是不同的分隔符,以及每个分隔符的含义.
小智 28
我很好奇,所以我进行了测试.我使用了以下代码:
<?php
ini_set('memory_limit', '1024M');
define ('CORE_PATH', '/Users/foo');
define ('DS', DIRECTORY_SEPARATOR);
$numtests = 1000000;
function test1($numtests)
{
$CORE_PATH = '/Users/foo';
$DS = DIRECTORY_SEPARATOR;
$a = array();
$startmem = memory_get_usage();
$a_start = microtime(true);
for ($i = 0; $i < $numtests; $i++) {
$a[] = sprintf('%s%sDesktop%sjunk.php', $CORE_PATH, $DS, $DS);
}
$a_end = microtime(true);
$a_mem = memory_get_usage();
$timeused = $a_end - $a_start;
$memused = $a_mem - $startmem;
echo "TEST 1: sprintf()\n";
echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}
function test2($numtests)
{
$CORE_PATH = '/Users/shigh';
$DS = DIRECTORY_SEPARATOR;
$a = array();
$startmem = memory_get_usage();
$a_start = microtime(true);
for ($i = 0; $i < $numtests; $i++) {
$a[] = $CORE_PATH . $DS . 'Desktop' . $DS . 'junk.php';
}
$a_end = microtime(true);
$a_mem = memory_get_usage();
$timeused = $a_end - $a_start;
$memused = $a_mem - $startmem;
echo "TEST 2: Concatenation\n";
echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}
function test3($numtests)
{
$CORE_PATH = '/Users/shigh';
$DS = DIRECTORY_SEPARATOR;
$a = array();
$startmem = memory_get_usage();
$a_start = microtime(true);
for ($i = 0; $i < $numtests; $i++) {
ob_start();
echo $CORE_PATH,$DS,'Desktop',$DS,'junk.php';
$aa = ob_get_contents();
ob_end_clean();
$a[] = $aa;
}
$a_end = microtime(true);
$a_mem = memory_get_usage();
$timeused = $a_end - $a_start;
$memused = $a_mem - $startmem;
echo "TEST 3: Buffering Method\n";
echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}
function test4($numtests)
{
$CORE_PATH = '/Users/shigh';
$DS = DIRECTORY_SEPARATOR;
$a = array();
$startmem = memory_get_usage();
$a_start = microtime(true);
for ($i = 0; $i < $numtests; $i++) {
$a[] = "{$CORE_PATH}{$DS}Desktop{$DS}junk.php";
}
$a_end = microtime(true);
$a_mem = memory_get_usage();
$timeused = $a_end - $a_start;
$memused = $a_mem - $startmem;
echo "TEST 4: Braced in-line variables\n";
echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}
function test5($numtests)
{
$a = array();
$startmem = memory_get_usage();
$a_start = microtime(true);
for ($i = 0; $i < $numtests; $i++) {
$CORE_PATH = CORE_PATH;
$DS = DIRECTORY_SEPARATOR;
$a[] = "{$CORE_PATH}{$DS}Desktop{$DS}junk.php";
}
$a_end = microtime(true);
$a_mem = memory_get_usage();
$timeused = $a_end - $a_start;
$memused = $a_mem - $startmem;
echo "TEST 5: Braced inline variables with loop-level assignments\n";
echo "TIME: {$timeused}\nMEMORY: $memused\n\n\n";
}
test1($numtests);
test2($numtests);
test3($numtests);
test4($numtests);
test5($numtests);
Run Code Online (Sandbox Code Playgroud)
......得到了以下结果.附图.显然,就时间和内存消耗而言,sprintf是效率最低的方法.编辑:在另一个标签中查看图像,除非您有鹰视觉.

Sea*_*ney 12
当您进行定时比较时,差异非常小,不太相关.自从选择使您的代码更易于阅读和理解之后,它会做得更多.
nig*_*der 12
PHP中不需要StringBuilder模拟.
我做了几个简单的测试:
在PHP中:
$iterations = 10000;
$stringToAppend = 'TESTSTR';
$timer = new Timer(); // based on microtime()
$s = '';
for($i = 0; $i < $iterations; $i++)
{
$s .= ($i . $stringToAppend);
}
$timer->VarDumpCurrentTimerValue();
$timer->Restart();
// Used purlogic's implementation.
// I tried other implementations, but they are not faster
$sb = new StringBuilder();
for($i = 0; $i < $iterations; $i++)
{
$sb->append($i);
$sb->append($stringToAppend);
}
$ss = $sb->toString();
$timer->VarDumpCurrentTimerValue();
Run Code Online (Sandbox Code Playgroud)
在C#(.NET 4.0)中:
const int iterations = 10000;
const string stringToAppend = "TESTSTR";
string s = "";
var timer = new Timer(); // based on StopWatch
for(int i = 0; i < iterations; i++)
{
s += (i + stringToAppend);
}
timer.ShowCurrentTimerValue();
timer.Restart();
var sb = new StringBuilder();
for(int i = 0; i < iterations; i++)
{
sb.Append(i);
sb.Append(stringToAppend);
}
string ss = sb.ToString();
timer.ShowCurrentTimerValue();
Run Code Online (Sandbox Code Playgroud)
结果:
10000次迭代:
1)PHP,普通级联:~6ms
2)PHP,使用StringBuilder:~5 ms
3)C#,普通级联:~520ms
4)C#,使用StringBuilder:~1ms
100000次迭代:
1)PHP,普通级联:~63ms
2)PHP,使用StringBuilder:~555ms
3)C#,普通级联:~91000ms // !!!
4)C#,使用StringBuilder:~17ms
oss*_*sys 10
我知道你在说什么.我刚刚创建了这个简单的类来模拟Java StringBuilder类.
class StringBuilder {
private $str = array();
public function __construct() { }
public function append($str) {
$this->str[] = $str;
}
public function toString() {
return implode($this->str);
}
}
Run Code Online (Sandbox Code Playgroud)
PHP字符串是可变的.您可以更改这样的特定字符:
$string = 'abc';
$string[2] = 'a'; // $string equals 'aba'
$string[3] = 'd'; // $string equals 'abad'
$string[5] = 'e'; // $string equals 'abad e' (fills character(s) in between with spaces)
Run Code Online (Sandbox Code Playgroud)
你可以将字符附加到这样的字符串:
$string .= 'a';
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
47103 次 |
| 最近记录: |