Mendapatkan karakter pertama dari string dengan $ str [0]

276

Saya ingin mendapatkan huruf pertama dari sebuah string dan saya perhatikan itu $str[0]sangat bagus. Saya hanya tidak yakin apakah ini 'praktik yang baik', karena notasi itu umumnya digunakan dengan array. Fitur ini sepertinya tidak terdokumentasi dengan baik jadi saya beralih kepada kalian untuk memberi tahu saya apakah boleh - dalam segala hal - untuk menggunakan notasi ini?

Atau haruskah saya tetap berpegang pada kebaikan substr($str, 0, 1)?

Juga, saya perhatikan bahwa kurung kurawal ( $str{0}) berfungsi juga. Ada apa dengan itu?

Tatu Ulmanen
sumber
5
ditambah 1 untuk "substr baik" ($ str, 0, 1) ".
Santiago berhenti SO

Jawaban:

390

Iya. String dapat dilihat sebagai array karakter, dan cara untuk mengakses posisi array adalah dengan menggunakan []operator. Biasanya tidak ada masalah sama sekali dalam menggunakan $str[0](dan saya cukup yakin ini jauh lebih cepat daripada substr()metode).

Hanya ada satu peringatan dengan kedua metode: mereka akan mendapatkan byte pertama , bukan karakter pertama . Ini penting jika Anda menggunakan penyandian multibyte (seperti UTF-8). Jika Anda ingin mendukungnya, gunakan mb_substr(). Boleh dibilang, Anda harus selalu mengasumsikan input multibyte hari ini, jadi ini adalah pilihan terbaik , tetapi akan sedikit lebih lambat.

Gadaian
sumber
7
Apakah PHP $ str [0] memperhitungkan bahwa mungkin ada karakter panjang 2Byte? UTF dan semacamnya? (meskipun substr () juga tidak membantu!)
Tomer W
77
Jika Anda ingin menjadi super aman, Anda harus menggunakannya mb_substr($str, 0, 1, 'utf-8')sehingga Anda tidak memotong string multibyte.
Vic
18
Meskipun ini lebih pendek dan lebih mudah diingat daripada substr($str, 0, 1), ini membingungkan siapa yang membaca kode.
trante
10
Pilihan antara tanda kurung siku dan substr () sebagian besar adalah masalah preferensi, tetapi perlu diketahui bahwa hasilnya berbeda ketika diterapkan pada string kosong. Jika $ s = "" maka $ s [] === "", tetapi substr ($ s, 0, 1) === false.
xtempore
9
Jika $ s = "" maka $ s [0] akan menghasilkan "Pemberitahuan: Offset string tidak diinisialisasi: 0" sedangkan substr ($ s, 0, 1) tidak akan.
chris
46

Sintaks {} tidak digunakan pada PHP 5.3.0. Kurung kotak direkomendasikan.

Michael Morton
sumber
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: pada tautan yang Anda berikan, saya perhatikan mereka menghapus catatan pada manual PHP yang hanya mereka tinggalkan: Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose.Jadi saya bertanya-tanya apakah mereka memutuskan bahwa penggunaan {}TIDAK ditinggalkan lagi pada PHP 6
Marco Demaio
1
@MarcoDemaio Tautan sekarang memberi tahu apa yang dikatakan MichaelMorton.
Tino
1
"tidak memberikan indikasi penghentian" - Memang, pesan penghentian telah dihapus dalam revisi 304518 - 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/language/…
VolkerK
Sampai hari ini (10 Mei 18), kutipan dari dokumen PHP yang disukai : Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. Sepertinya sintaks ini akan tetap untuk sementara waktu.
Fr0zenFyr
25

Katakanlah Anda hanya ingin char pertama dari bagian $ _POST, sebut saja 'ketik'. Dan $ _POST ['type'] saat ini 'Control'. Jika dalam hal ini jika Anda gunakan $_POST['type'][0], atau substr($_POST['type'], 0, 1)Anda akan Ckembali.

Namun, jika sisi klien adalah untuk memodifikasi data mereka mengirimkan, dari typeke type[]misalnya, dan kemudian mengirim 'Control' dan 'Test' sebagai data untuk array ini, $_POST['type'][0]sekarang akan kembali Controldaripada Csedangkan substr($_POST['type'], 0, 1)hanya akan hanya gagal.

Jadi ya, mungkin ada masalah dengan penggunaan $str[0], tetapi itu tergantung pada keadaan di sekitarnya.

gattsbr
sumber
2
Sebagai catatan untuk menghindari masalah khusus ini dan dalam setiap kasus seseorang harus selalu melakukan validasi data. if (true === is_string($_POST['type']))
fyrye
13

Satu-satunya keraguan saya adalah seberapa bisa diterapkan teknik ini pada string multi-byte, tetapi jika itu bukan pertimbangan, maka saya curiga Anda dilindungi. (Jika ragu, mb_substr()tampaknya pilihan yang jelas aman.)

Namun, dari perspektif gambaran besar, saya harus bertanya-tanya seberapa sering Anda perlu mengakses karakter ke-n dalam sebuah string agar ini menjadi pertimbangan utama.

John Parker
sumber
9

Ini akan bervariasi tergantung pada sumber daya, tetapi Anda dapat menjalankan skrip di bawah dan lihat sendiri;)

<?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;
?>

Beberapa nomor referensi (pada mesin CoreDuo lama)

$ 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

Tampaknya menggunakan []atau {}operator kurang lebih sama.

Willy Stadnick
sumber
2
Tes yang bagus! Beberapa angka dari Xeon yang berusia 3 tahun: rata-rata float microtime menggunakan "array []" adalah 2.2427082061768E-7 rata-rata float microtime menggunakan "substr ()" adalah 3.9647579193115E-7 rata-rata float microtime menggunakan "array {}" adalah 2.1522283554077E-7
Ellert van Koperen
untuk pengukuran yang akurat, Anda harus lebih baik melakukan microtime dari loop, dan jangan mencampur pendekatan yang berbeda dalam loop yang sama.
PypeBros
1
tidak mencampurkan eksekusi testAdan testBdalam loop yang sama berarti Anda mampu mendeteksi mis. fakta bahwa itu testBadalah pembunuh-cache sementara testAramah-cache. Ketika keduanya berada di loop yang sama, mereka diukur memiliki timing yang sama karena caching yang testBtercemar testA.
PypeBros
1
sama halnya, saya akan menghindari menghasilkan string atau random dalam loop pengujian dan membuatnya siap dalam array di dekatnya.
PypeBros
1
-1; mengesampingkan mekanisme waktu yang dipertanyakan (akan lebih baik untuk mengatur waktu banyak operasi daripada waktu mereka satu per satu; saya khawatir setelah membaca ini bahwa hanya waktu yang diambil untuk melakukan microtime()panggilan akan membuat sebagian besar perbedaan waktu, meskipun secara eksperimental yang tampaknya menjadi tidak benar), tidak ada alasan untuk peduli tentang perbedaan kecepatan kecil di sini. Ini sepersekian dari sepersejuta detik; kapan ini pernah akan menjadi masalah?
Mark Amery
6

Berbicara sebagai manusia biasa, saya akan tetap dengan $str[0]. Sejauh yang saya ketahui, lebih cepat untuk memahami arti dari $str[0]sekilas daripada substr($str, 0, 1). Ini mungkin bermuara pada masalah preferensi.

Sejauh kinerja berjalan, baik, profil profil profil. :) Atau Anda dapat mengintip kode sumber PHP ...

Stephen
sumber
6
$str = 'abcdef';
echo $str[0];                 // a
Jakir Hossain
sumber
6
-1; pertanyaan OP adalah apakah sintaks ini adalah praktik yang buruk, dan Anda telah merespons dengan ... mengulangi sintaks, tanpa komentar apa pun? Ini bukan jawaban.
Mark Amery
5

Dalam kasus penggunaan string multibyte (unicode) str[0]dapat menyebabkan masalah. mb_substr()adalah solusi yang lebih baik. Sebagai contoh:

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

Beberapa detail di sini: Dapatkan karakter pertama dari string UTF-8

Sergey Burish
sumber
Terima kasih atas solusi ini! jika karakter pertama adalah unicode, [] tidak akan berfungsi
SunB
1

Saya telah menggunakan notasi itu sebelumnya, tanpa efek samping yang buruk dan tidak ada kesalahpahaman. Masuk akal - string hanyalah array karakter, setelah semua.

Kaleb Brasee
sumber
Tidak, string bukan array karakter (setidaknya karena PHP menggunakan kedua istilah itu). -1.
Mark Amery
@ Gattsbr secara internal mereka, tetapi sejauh model PHP mengekspos pergi, mereka pada dasarnya berbeda. Mengakses offset menggunakan notasi braket persegi adalah satu-satunya operasi yang sama-sama mereka miliki dengan array; fungsi string tidak bekerja pada array, atau vica versa, dan sintaks append array ( $arr[] = $new_element) tidak berfungsi pada string. Karena itu, saya tidak berpikir memahami string sebagai array karakter berguna.
Mark Amery
@markamery lebih baik menulis ulang manual php.net kemudian memasukkan teknis yang sangat kecil.
gattsbr