İki dizeyi birlikte eklemek için en iyi yolu nedir?

11 Cevap php

Ben onlar sayılar gibi gibi sayılar yana, dizeleri değiştirilemez birlikte dizeleri eklemek için kötü bir uygulama olduğunu (ben codinghorror üzerine düşündüm) somewehere okuyun. Böylece, birbirine ekleyerek yeni bir dize oluşturur. Yani, performans odaklanarak zaman birlikte iki dizeleri eklemek için en iyi yolu, ne olduğunu, merak ediyorum?

Bu dört hangisi daha iyi, ya da daha başka bir yolu var mı?

//Note that normally at least one of these two strings is variable
$str1 = 'Hello ';
$str2 = 'World!'; 
$output1 = $str1.$str2; //This is said to be bad

$str1 = 'Hello ';
$output2 = $str1.'World!'; //Also bad

$str1 = 'Hello';
$str2 = 'World!';
$output3 = sprintf('%s %s', $str1, $str2); //Good?
//This last one is probaply more common as:
//$output = sprintf('%s %s', 'Hello', 'World!');

$str1 = 'Hello ';
$str2 = '{a}World!';
$output4 = str_replace('{a}', $str1, $str2);

Hatta önemli mi?

11 Cevap

Her zaman birlikte iki veya daha fazla dizeleri bitiştirmek whe yeni bir dizeyi oluşturmak için gidiyoruz. Bu mutlaka 'kötü' değil, ama (bir döngü içinde bitiştirmelerini binlerce / milyonlarca gibi) bazı senaryolarda performans etkileri olabilir. Ben bir PHP adam değilim, bu yüzden sana dizeleri bitiştirmek farklı şekillerde semantik üzerinde herhangi bir tavsiye veremem, ama bir tek dize birleştirme (ya da birkaç) için, sadece okunabilir yapmak. Bunlardan az sayıda bir performans isabet görmek için gidiş değildir.

String Concatenation with a dot is definitely the fastest one of the three methods. You will always create a new string, whether you like it or not. Most likely the fastest way would be:

$str1 = "Hello";
$str1 .= " World";

Bu dizge içinde semboller ayrıştırma için ek yükü üretecektir gibi $result = "$str1$str2"; gibi çift tırnak içine koymayın.

Sadece echo ile çıkışı için kullanmak için gidiyoruz eğer, bu yeni bir dize oluşturmak olmayacak gibi, o, bunu birden fazla parametre iletebilirsiniz yankı özelliğini kullanın:

$str1 = "Hello";
$str2 = " World";
echo $str1, $str2;

PHP davranır dizeleri ve dize birleştirme interpolasyon nasıl hakkında daha fazla bilgi için check out Sarah Goleman's blog.

Burada hızlı ve kirli test kodu performans darboğazları anlamak için, bu.

Single concat:

$iterations = 1000000;
$table = 'FOO';
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = sprintf('DELETE FROM `%s` WHERE `ID` = ?', $table);
}
echo 'single sprintf,',(microtime(true) - $time)."\n";

$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = 'DELETE FROM `' . $table . '` WHERE `ID` = ?';
}
echo 'single concat,',(microtime(true) - $time)."\n";

$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = "DELETE FROM `$table` WHERE `ID` = ?";
}
echo 'single "$str",',(microtime(true) - $time)."\n";

Ben bu sonuçlar alırsınız:

single sprintf,0.66322994232178
single concat,0.18625092506409 <-- winner
single "$str",0.19963216781616

Many concats (10):

$iterations = 1000000;
$table = 'FOO';
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = sprintf('DELETE FROM `%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s` WHERE `ID` = ?', $table, $table, $table, $table, $table, $table, $table, $table, $table, $table);
}
echo 'many sprintf,',(microtime(true) - $time)."\n";

$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = 'DELETE FROM `' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '` WHERE `ID` = ?';
}
echo 'many concat,',(microtime(true) - $time)."\n";

$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
        $sql = "DELETE FROM `$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table` WHERE `ID` = ?";
}
echo 'many "$str",',(microtime(true) - $time)."\n";

Sonuçlar:

many sprintf,2.0778489112854
many concats,1.535336971283
many "$str",1.0247709751129 <-- winner

Sonuç olarak, bu nokta üzerinden tek concat (.) Karakter hızlı olduğu belli olur. Birçok concats var ne zaman ve durumlarda, en iyi performans yöntemi "injection: $inject" sözdizimi aracılığıyla doğrudan dize enjeksiyon kullanıyor.

Metnin onun gerçekten büyük miktarda gerçekten önemli değil tabii.

As the others said, $str1 . $str2 is perfectly OK in most cases, except in (big) loops.
Note that you overlook some solutions:

$output = "$str1$str2";

ve dizeleri sayıda, sen onları bir diziye koymak ve bunların dışında bir dize almak için çöktüğünü () kullanabilirsiniz.

Oh, ve "dizeleri ekleyerek" kötü, ya da en azından belirsiz sesler. Çoğu dilde, biz dize konsatenasyonundan konuşmayı tercih ederim.

Looong döngüde kullanılan sürece önemli değildir. Olağan durumlarda birkaç işlemci döngüleri kaybetmiş olsa bile, kod okunabilirliği odaklanmak.

Example 1 and 2 benzer, ben çok fark olması gerektiğini sanmıyorum, bu tüm hızlısı olacaktır. No: 1 biraz daha hızlı olabilir.

Example 3 yavaş olabilir, sprintf format olarak ('% s% s') ayrıştırılması gerekir olacaktır.

Example 4 bir dize içinde arama içerir ki, yerini alıyor - yapmak için ek bir şey, daha fazla zaman alır.

Ama öncelikle, dizelerin bir performans sorunu birleştirerek edilir? Çok ihtimal, bunu çalıştırmak için sürer ne kadar zaman ölçmek için kod profil olmalıdır. Sonra, yine farklı bir ve zaman bitiştirme yöntemini değiştirin.

Eğer bir sorun olarak tanımlamak ise, (bazı bulunabilir vardır) php dize kurucu bir sınıf için googling deneyin veya kendi yazmak.

Dize birleştirme işlemleri 3 tipi vardır.

, 2 dize almak bellek boyutu uzunluğu1 + length2 tahsis ve yeni belleğe her kopyalayın bağlamak. 2 dizeleri için hızlı. Ancak, 10 dizeleri bitiştirmek sonra 9 concatı operasyonları gerektirir. Kullanılan bellek vb 10 kez, 2 dize 10 kez, 3 dize 9 kez, 4 dize 8 kez, 1. dize X +1 + çalıştırır (X-1) * Her bir döngü daha fazla bellek kullanan 2 işlemleri.

sprintf (array_merge, vb katılmak), birlikte tüm dizeleri almak onların uzunluğunu Özetle, boyut toplamı yeni bir dize tahsis, bundan sonra ilgili yerine her dize kopyalayın. kullanılan bellek bütün ilk dizeleri 2 * uzunluğu ve işlemleri 2 * X (her boy, her kopya) olduğunu

ob (çıkış tampon) bunun için bir genel 4k yığın ve kopyaları her dize ayırmak. bellek 4k + Her başlangıç ​​dizesi, işlemleri = 2 + X. (başlangıç, bitiş, her kopya)

Pick your poison. OB is like using a memory atom bomb to join 2 small strings, but is very effective when there are many joins, loops, conditions or the additions are too dynamic for a clean sprintf. concat is the most efficient to join a few fixed strings, sprintf which works better for building a string out of fixed values at one time.

Ben rutin php, bu durumda kullandığı bilmiyorum: "$ x $ y $ z", sadece bir satır içi $ x azaltılmış olabilir. "." $ Y. "." $ Z

Okuduğunuz tavsiyem virgül kullanmak hızlıdır hangi için echo fonksiyonu, örneğin ilişkili olabilir:

echo $str1, $str2;

Başka bir yaklaşım (. Operatörü kullanarak örneğin) bir değişken bir dize oluşturmak için daha sonra sonunda bütün dize echo.

(Eğer sayı anlamlı yapmak için 1,000 veya 100,000 kez tekrarlar, örneğin bir döngü yapmak gerekir) microtime işlevini kullanarak bunu kendiniz test edebilir. Ama yayınlanmıştır dört, ilk hızlı olması muhtemeldir. Aynı zamanda en okunabilir - diğerleri gerçekten programlı mantıklı değil.

Bu 2 dizeleri için bir çözüm değil, ancak iyi yolu gibi daha dizeleri katılmadan düşünmeye zaman:

$tmp=srray();
for(;;) $tmp[]='some string';
$str=implode('',$tmp);

Onlara yüz kere katılmak yerine, dizi elemanı oluşturmak ve hepsini bir kerede katılmak için hızlı.

Ben diğer birçok dilde (örneğin Python) olarak, ancak, bir PHP gurusu değilim, birçok küçük dizeleri üzerinden uzun bir dize oluşturmak için en hızlı yolu bir listeye bağlamak istediğiniz dizeleri eklemek için, ve sonra onlara katılmak için Bir yerleşik kullanarak yöntemi katılın. Örneğin:

$result = array();
array_push("Hello,");
array_push("my");
array_push("name");
array_push("is");
array_push("John");
array_push("Doe.");
$my_string = join(" ", $result);

Eğer sıkı bir döngü içinde büyük bir dize bina varsa, bunu yapmak için en hızlı yolu diziye ve sonra sonunda dizi katılmadan gereğidir.

Not: Tüm bu tartışma bir array_push performansına bağlı. Bu çok büyük dizeleri üzerinde etkili olması için sırayla bir list için dizeleri ekleme gerekir. Böyle bir yapı php dizi yeni eleman eklenmesi en hızlı olup mevcut veya Çünkü php benim sınırlı kalma, ben emin değilim.

Bu Konuya son yazıdan sonra yaklaşık 2 yıldır, ben aşağıda çözüm sıkı döngüler büyük sayıda hızlı olabileceğini düşünüyorum:

ob_start();

echo $str1;
echo $str2;
.
.
.
echo $str_n;

$finalstr = ob_get_clean();

Bu yöntem, tüm dizeler düz bir depolama ve hiçbir işlem veya birleştirme yükü sağlar. Son satır kod ile, siz de tüm tampon olsun. Sen güvenle yerine bağımsız yansımaları, döngüler çalıştırabilirsiniz.