$ Str [0] ile bir dizenin ilk karakterini elde etme


276

Bir dizenin ilk harfini almak istiyorum ve bunun $str[0]işe yaradığını fark ettim . Bunun 'iyi uygulama' olup olmadığından emin değilim, çünkü bu gösterim genellikle dizilerde kullanılır. Bu özellik çok iyi belgelenmiş gibi görünmüyor, bu yüzden bana bu gösterimi kullanmanın uygun olup olmadığını söylemek için size dönüyorum?

Yoksa sadece iyi olanlara substr($str, 0, 1)mı bağlı kalmalıyım ?

Ayrıca, kıvırcık parantezlerin ( $str{0}) de işe yaradığını belirttim . Bunun nesi var?


5
artı 1 "iyi ol 'substr ($ str, 0, 1)" için.
Santiago,

Yanıtlar:


390

Evet. Dizeler karakter dizileri olarak görülebilir ve dizinin konumuna erişmenin yolu []operatörü kullanmaktır . Genellikle kullanımda hiçbir sorun yoktur $str[0](ve substr()yöntemden çok daha hızlı olduğundan eminim ).

Her iki yöntemle de sadece bir uyarı var: ilk karakterden ziyade ilk baytı alacaklar . Çok baytlı kodlamalar (UTF-8 gibi) kullanıyorsanız bu önemlidir. Bunu desteklemek istiyorsanız kullanın . Tartışmalı olarak, bu günlerde her zaman çok baytlı girdi varsaymalısınız, bu yüzden bu en iyi seçenektir, ancak biraz daha yavaş olacaktır.mb_substr()


7
PHP $ str [0] 2Byte uzun karakter olabileceğini dikkate alıyor mu? UTF ve benzeri? (substr () de ona yardım etmese bile!)
Tomer W

77
Ekstra süper güvenli olmak istiyorsanız, mb_substr($str, 0, 1, 'utf-8')çok baytlı bir dizeyi kısaltmamak için gitmelisiniz .
Vic

18
Bu daha kısa ve hatırlanması daha kolay olmasına rağmen substr($str, 0, 1), bu kodu kimin okuduğunu karıştırır.
trante

10
Köşeli ayraçlar ve substr () arasındaki seçim büyük ölçüde bir tercih meselesidir, ancak boş bir dizeye uygulandığında sonucun farklı olduğunu unutmayın. $ S = "" ise $ s [] === "", ancak substr ($ s, 0, 1) === false.
xtempore

9
$ S = "" ise, $ s [0] bir "Not: Başlatılmamış dize uzaklığı: 0" üretirken substr ($ s, 0, 1) oluşturmaz.
chris

46

{} Sözdizimi PHP 5.3.0'dan itibaren kullanımdan kaldırılmıştır. Köşeli parantez önerilir.


14
docs.php.net/language.types.string :Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. However, this syntax is deprecated as of PHP 5.3.0. Use square brackets instead, such as $str[42].
VolkerK

4
@VolkerK: sağladığınız bağlantıda, sadece bıraktıkları PHP kılavuzundaki notu kaldırdıklarını fark ettim: Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose.Bu yüzden {}, artık PHP 6
Marco Demaio

1
@MarcoDemaio Bağlantı şimdi MichaelMorton'un ne söylediğini anlatıyor.
Tino

1
Gerçekten de, kullanımdan kaldırılması mesajı revizyon 304.518 kaldırılmıştır - - "kaldırma işleminin hiçbir gösterge verir" The curly-brackets-string-index-accessor-syntax does not emit any deprecation notice, although the original notice have been on and off for PHP 5.x, it does not in the current version, thrus we should not label it as deprecated. Related to bug #52254- svn.php.net/repository/phpdoc/en/trunk/language/types/...
VolkerK

Bugün itibariyle (10 Mayıs'18), sevilen PHP belgelerinden bir alıntı : Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. Bu sözdiziminin bir süre kalacağı anlaşılıyor .
Fr0zenFyr

25

Diyelim ki sadece $ _POST parçasının ilk karakterini istiyorsunuz, 'tür' diyelim. Ve $ _POST ['type'] şu anda 'Control'. Bu durumda kullanırsanız $_POST['type'][0], ya da geri substr($_POST['type'], 0, 1)alacaksınız C.

İstemci tarafı nereden, göndermek verileri değiştirmek olsaydı Ancak, typehiç type[]örneğin, ardından bu dizi için veri olarak 'Kontrol' ve 'Testi' yazıp $_POST['type'][0]hemen dönecektir Controlziyade Coysa substr($_POST['type'], 0, 1)sadece sadece başarısız olacaktır.

Yani evet, kullanımla ilgili bir sorun olabilir $str[0], ancak bu çevredeki duruma bağlıdır.


2
Bu özel konuyu atlatmak için bir yan not olarak ve her iki durumda da her zaman veri doğrulaması yapılmalıdır. if (true === is_string($_POST['type']))
fyrye

13

Tek şüphe bu tekniğin çok baytlık dizelerde ne kadar geçerli olabileceğidir, ancak bu bir dikkate alınmazsa, kapsadığınızdan şüphelenirim. (Şüpheniz varsa, mb_substr()açıkça güvenli bir seçim gibi görünüyor.)

Ancak, büyük bir resim perspektifinden bakıldığında, bir anahtardaki 'n'th karakterine ne sıklıkta erişmeniz gerektiğini merak etmem gerekiyor.


9

Kaynaklara bağlı olarak değişir, ancak aşağıdaki komut dosyasını çalıştırabilir ve kendiniz görebilirsiniz;)

<?php
$tests = 100000;

for ($i = 0; $i < $tests; $i++)
{
    $string = md5(rand());
    $position = rand(0, 31);

    $start1 = microtime(true);
    $char1 = $string[$position];
    $end1 = microtime(true);
    $time1[$i] = $end1 - $start1;

    $start2 = microtime(true);
    $char2 = substr($string, $position, 1);
    $end2 = microtime(true);
    $time2[$i] = $end2 - $start2;

    $start3 = microtime(true);
    $char3 = $string{$position};
    $end3 = microtime(true);
    $time3[$i] = $end3 - $start3;
}

$avg1 = array_sum($time1) / $tests;
echo 'the average float microtime using "array[]" is '. $avg1 . PHP_EOL;

$avg2 = array_sum($time2) / $tests;
echo 'the average float microtime using "substr()" is '. $avg2 . PHP_EOL;

$avg3 = array_sum($time3) / $tests;
echo 'the average float microtime using "array{}" is '. $avg3 . PHP_EOL;
?>

Bazı referans numaraları (eski bir CoreDuo makinesinde)

$ php 1.php 
the average float microtime using "array[]" is 1.914701461792E-6
the average float microtime using "substr()" is 2.2536706924438E-6
the average float microtime using "array{}" is 1.821768283844E-6

$ php 1.php 
the average float microtime using "array[]" is 1.7251944541931E-6
the average float microtime using "substr()" is 2.0931363105774E-6
the average float microtime using "array{}" is 1.7225742340088E-6

$ php 1.php 
the average float microtime using "array[]" is 1.7293763160706E-6
the average float microtime using "substr()" is 2.1037721633911E-6
the average float microtime using "array{}" is 1.7249774932861E-6

[]Veya {}işleçlerini kullanmanın aşağı yukarı aynı olduğu anlaşılıyor .


2
Güzel test! 3 yaşındaki bir Xeon'dan bazı sayılar: "dizi []" kullanan ortalama şamandıra mikro zamanı 2.2427082061768E-7, "substr ()" kullanan ortalama şamandıra mikro zamanı 3.9647579193115E-7 "dizi {}" kullanan ortalama şamandıra mikro zamanı E-7
Ellert van Koperen

Doğru ölçümler için, mikro zamanı döngüden daha iyi yapmalısınız ve farklı döngüleri aynı döngü içinde karıştırmayın.
PypeBros

1
yürütülmesini karıştırmıyor testAve testBsen gerçeği örneğin saptayabilen aynı döngüler imkanları ölçüsünde testBiken önbelleği katil testAönbellek dostudur. İkisi de aynı döngü içerisindeyken, testBkirli zamanların testAönbelleğe alınması nedeniyle aynı zamanlamalara sahip oldukları ölçülür .
PypeBros

1
benzer şekilde, test döngülerinde dizeler veya rasgele üretmekten kaçınır ve yakındaki bir dizide hazır hale getiririm.
PypeBros

1
1; tartışmalı zamanlama mekanizmasını bir kenara bırakarak (birçok işlemi zamanlamak için onları birer birer zamanlamaktan daha iyi olurdu; Bunu okuduktan sonra, microtime()çağrı yaparken sadece zamanın çoğu zaman farkının çoğunu oluşturacağından endişeliyim , deneysel olarak görünüyor doğru olmasa da), buradaki küçük hız farkına dikkat etmek için hiçbir neden yoktur. Saniyenin milyonda biri kesir; bu olduğunu hiç önemi kalmayacak?
Mark Amery

6

Sadece ölümlü olarak konuşurken, buna bağlı kalacağım $str[0]. Endişe ettiğim kadarıyla, anlamını $str[0]bir bakışta kavramak daha hızlı substr($str, 0, 1). Bu muhtemelen bir tercih meselesine bağlı.

Performansa gelince, profil profil profili. :) Veya PHP kaynak koduna bakabilirsiniz ...


6
$str = 'abcdef';
echo $str[0];                 // a

6
1; OP'nin sorusu bu sözdiziminin kötü bir uygulama olup olmadığıydı ve siz herhangi bir yorum yapmadan sözdizimini tekrarlayarak cevap verdiniz mi? Bu bir cevap değil.
Mark Amery

5

Çok baytlı (unicode) dizgilerin kullanılması str[0]sorun yaratabilir. mb_substr()daha iyi bir çözümdür. Örneğin:

$first_char = mb_substr($title, 0, 1);

Burada bazı ayrıntılar: UTF-8 dizesinin ilk karakterini alın


Bu çözüm için teşekkürler! ilk karakter unicode ise, [] alışkanlık
SunB

1

Bu notasyonu daha önce de kullandım, hiçbir yan etkisi ve yanlış anlama olmadan. Her şeyden önce - bir dize sadece bir karakter dizisidir.


Hayır, bir dize bir karakter dizisi değildir (en azından PHP bu iki terimi kullandığından). -1.
Mark Amery


@gattsbr dahili olarak, ancak PHP'nin ortaya koyduğu modele göre, temelde farklı bir şey. Köşeli parantez notasyonunu kullanarak bir ofsete erişmek, dizilerle ortak oldukları tek işlemdir; dize işlevleri dizilerde çalışmaz, tersi de geçerlidir ve dizi ekleme sözdizimi ( $arr[] = $new_element) dizelerde çalışmaz. Bu nedenle, dizelerin karakter dizileri olarak düşünülmesinin yararlı olduğunu düşünmüyorum.
Mark Amery

@markamery daha sonra php.net el kitabının yeniden yazılması daha sonra böyle küçük bir teknik dahil etmek.
gattsbr
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.