Lấy ký tự đầu tiên của chuỗi bằng $ str [0]


275

Tôi muốn nhận được chữ cái đầu tiên của một chuỗi và tôi nhận thấy rằng nó $str[0]hoạt động rất tốt. Tôi chỉ không chắc liệu đây có phải là 'thực hành tốt' hay không, vì ký hiệu đó thường được sử dụng với các mảng. Tính năng này dường như không được ghi lại rõ ràng, vì vậy tôi sẽ chuyển sang các bạn để nói với tôi nếu nó ổn - về mọi phương diện - để sử dụng ký hiệu này?

Hay tôi chỉ nên bám vào ol 'tốt substr($str, 0, 1)?

Ngoài ra, tôi lưu ý rằng niềng răng xoăn ( $str{0}) cũng hoạt động. Có chuyện gì thế?


5
cộng 1 cho "chất nền ol 'tốt ($ str, 0, 1)".
Santiago rời khỏi SO

Câu trả lời:


388

Đúng. Các chuỗi có thể được xem như các mảng ký tự và cách để truy cập vị trí của một mảng là sử dụng []toán tử. Thông thường không có vấn đề gì trong việc sử dụng $str[0](và tôi khá chắc chắn là nhanh hơn nhiều so với substr()phương pháp).

Chỉ có một cảnh báo với cả hai phương thức: họ sẽ nhận được byte đầu tiên , thay vì ký tự đầu tiên . Điều này rất quan trọng nếu bạn đang sử dụng mã hóa đa bào (như UTF-8). Nếu bạn muốn hỗ trợ điều đó, hãy sử dụng mb_substr(). Có thể cho rằng, bạn nên luôn luôn giả định đầu vào đa bào trong những ngày này, vì vậy đây là lựa chọn tốt nhất , nhưng nó sẽ chậm hơn một chút.


7
PHP $ str [0] có tính đến việc có thể có 2 ký tự dài không? UTF và như vậy? (mặc dù chất nền () cũng không giúp được gì cho nó!)
Tomer W

77
Nếu bạn muốn cực kỳ an toàn, bạn nên đi cùng mb_substr($str, 0, 1, 'utf-8')để không cắt xén chuỗi đa bào.
Vic

18
Mặc dù điều này ngắn hơn và dễ nhớ hơn substr($str, 0, 1), nhưng điều này gây nhầm lẫn cho những người đọc mã.
trante

10
Sự lựa chọn giữa dấu ngoặc vuông và đế () phần lớn là vấn đề ưu tiên, nhưng lưu ý rằng kết quả sẽ khác nhau khi áp dụng cho một chuỗi rỗng. Nếu $ s = "" thì $ s [] === "", nhưng chất nền ($ s, 0, 1) === sai.
xtempore

9
Nếu $ s = "" thì $ s [0] sẽ tạo ra "Thông báo: offset chuỗi chưa được khởi tạo: 0" trong khi chất nền ($ s, 0, 1) sẽ không.
chris

46

Cú pháp {} không được dùng nữa kể từ PHP 5.3.0. Dấu ngoặc vuông được khuyến khích.


14
docs.php.net/lingu.types.opes :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: tại liên kết bạn cung cấp, tôi nhận thấy họ đã xóa ghi chú trong hướng dẫn sử dụng PHP mà họ chỉ để lại: Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose.Vì vậy, tôi tự hỏi liệu họ có quyết định rằng việc sử dụng {}KHÔNG bị phản đối nữa không kể từ PHP 6
Marco Demaio

1
@MarcoDemaio Liên kết bây giờ cho biết những gì MichaelMorton nói.
Tino

1
"không đưa ra dấu hiệu của deprecation" - Trên thực tế, thông điệp deprecation đã được loại bỏ trong phiên bản 304.518 - 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

Kể từ hôm nay (ngày 10 tháng 5 năm 18), một trích dẫn từ các tài liệu PHP được yêu thích : Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. Có vẻ như cú pháp này sẽ tồn tại trong một thời gian.
Fr0zenFyr

25

Hãy nói rằng bạn chỉ muốn char đầu tiên từ một phần của $ _POST, hãy gọi nó là 'loại'. Và $ _POST ['type'] hiện tại là 'Control'. Nếu trong trường hợp này nếu bạn sử dụng $_POST['type'][0], hoặc substr($_POST['type'], 0, 1)bạn sẽ nhận Clại.

Tuy nhiên, nếu các mặt hàng khác là để thay đổi dữ liệu mà họ gửi cho bạn, từ typeđể type[]ví dụ, và sau đó gửi 'kiểm soát' và 'thử nghiệm' như các dữ liệu cho mảng này, $_POST['type'][0]bây giờ sẽ trở lại Controlchứ không phải Cngược lại substr($_POST['type'], 0, 1)sẽ đơn giản chỉ là thất bại.

Vì vậy, có, có thể có một vấn đề với việc sử dụng $str[0], nhưng điều đó phụ thuộc vào hoàn cảnh xung quanh.


2
Là một lưu ý phụ để tránh sự cố cụ thể này và trong cả hai trường hợp, người ta phải luôn luôn thực hiện xác nhận dữ liệu. if (true === is_string($_POST['type']))
fyrye

13

Nghi ngờ duy nhất của tôi sẽ là cách áp dụng kỹ thuật này trên các chuỗi nhiều byte, nhưng nếu đó không phải là một sự cân nhắc, thì tôi nghi ngờ bạn được bảo vệ. (Nếu nghi ngờ, mb_substr()có vẻ như một sự lựa chọn rõ ràng an toàn.)

Tuy nhiên, từ góc độ hình ảnh lớn, tôi phải tự hỏi mức độ thường xuyên bạn cần truy cập vào ký tự thứ n trong chuỗi để đây là một sự cân nhắc quan trọng.


9

Nó sẽ thay đổi tùy thuộc vào tài nguyên, nhưng bạn có thể chạy tập lệnh dưới đây và tự mình xem;)

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

Một số số tham chiếu (trên máy CoreDuo cũ)

$ 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

Dường như sử dụng []hoặc {}khai thác là nhiều hơn hoặc ít hơn như nhau.


2
Thử nghiệm tốt đẹp! Một số số từ Xeon 3 tuổi: microtime float trung bình sử dụng "mảng []" là 2.2427082061768E-7 microtime float trung bình sử dụng "chất nền ()" là 3.9647579193115E-7 microtime float trung bình sử dụng "mảng {}" là 2.1522283554077E-7
Ellert van Koperen

Để đo chính xác, bạn nên sử dụng microtime trong vòng lặp và không trộn lẫn các cách tiếp cận khác nhau trong cùng một vòng.
PypeBros

1
không trộn lẫn việc thực thi testAtestBtrong cùng một vòng lặp có nghĩa là bạn có khả năng phát hiện, ví dụ thực tế testBlà trình diệt testAbộ đệm trong khi thân thiện với bộ đệm. Khi cả hai trong cùng một vòng lặp, chúng được đo có cùng thời gian vì bộ nhớ đệm testBbị ô nhiễm testA.
PypeBros

1
tương tự, tôi sẽ tránh tạo ra các chuỗi hoặc randoms trong các vòng kiểm tra và để chúng sẵn sàng trong một mảng gần đó.
PypeBros

1
-1; Gác lại những cơ chế thời gian đáng ngờ (nó sẽ tốt hơn nếu thời gian nhiều hoạt động hơn là thời gian họ cùng một lúc, tôi lo lắng khi đọc bài viết này mà chỉ thời gian thực hiện làm microtime()cuộc gọi sẽ tạo nên hầu hết các thời gian khác nhau, mặc dù thực nghiệm mà dường như không đúng sự thật), không có lý do gì để quan tâm đến sự khác biệt tốc độ nhỏ bé ở đây. Đó là một phần của một phần triệu giây; khi được này bao giờ sẽ có vấn đề?
Đánh dấu Amery

6

Nói như một phàm nhân, tôi sẽ gắn bó $str[0]. Theo như tôi quan tâm, việc nắm bắt ý nghĩa của $str[0]cái nhìn nhanh hơn là nhanh hơn substr($str, 0, 1). Điều này có lẽ sôi lên đến một vấn đề ưu tiên.

Theo như hiệu suất, tốt, hồ sơ hồ sơ hồ sơ. :) Hoặc bạn có thể xem mã nguồn PHP ...


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

6
-1; Câu hỏi của OP là liệu cú pháp này có phải là một thực tiễn xấu hay không và bạn đã trả lời bằng cách ... lặp lại cú pháp mà không có bất kỳ lời bình luận nào? Đây không phải là một câu trả lời.
Đánh dấu Amery

5

Trong trường hợp sử dụng chuỗi multibyte (unicode) str[0]có thể gây rắc rối. mb_substr()là một giải pháp tốt hơn. Ví dụ:

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

Một số chi tiết tại đây: Nhận ký tự đầu tiên của chuỗi UTF-8


Cảm ơn bạn cho giải pháp này! nếu ký tự đầu tiên là unicode, [] sẽ không hoạt động
SunB 24/03/19

1

Tôi cũng đã sử dụng ký hiệu đó trước đây, không có tác dụng phụ xấu và không có sự hiểu lầm. Nó có ý nghĩa - sau tất cả, một chuỗi chỉ là một mảng các ký tự.


Không, một chuỗi không phải là một mảng các ký tự (ít nhất là khi PHP sử dụng hai thuật ngữ đó). -1.
Đánh dấu Amery


@gattsbr bên trong họ là như vậy, nhưng theo như mô hình mà PHP trưng bày, chúng là một thứ khác biệt cơ bản. Truy cập một phần bù bằng ký hiệu dấu ngoặc vuông là thao tác duy nhất mà chúng có chung với mảng; các hàm chuỗi không hoạt động trên các mảng, cũng không phải là vica và cú pháp nối thêm mảng ( $arr[] = $new_element) không hoạt động trên các chuỗi. Như vậy, tôi không nghĩ việc hình thành chuỗi vì mảng ký tự là hữu ích.
Mark Amery

@markamery tốt hơn nên viết lại hướng dẫn sử dụng php.net sau đó để bao gồm một kỹ thuật rất nhỏ.
gattsbr
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.