Получение первого символа строки с помощью $ str [0]

Я хочу получить первую букву строки и заметил, что $str[0] отлично работает. Я просто не уверен, является ли это «хорошей практикой», поскольку такая нотация обычно используется с массивами. Эта функция, похоже, не очень хорошо документирована, поэтому я обращаюсь к вам, ребята, чтобы сказать мне, можно ли во всех отношениях использовать эту нотацию?

Или я должен просто придерживаться старого доброго substr($str, 0, 1)?

Также я заметил, что фигурные скобки ($str{0}) тоже работают. Что с этим?


person Tatu Ulmanen    schedule 28.12.2009    source источник
comment
плюс 1 за старый добрый substr ($ str, 0, 1).   -  person Santiago quits SO    schedule 31.10.2017


Ответы (9)


да. Строки можно рассматривать как символьные массивы, а способ доступа к позиции массива - использовать оператор []. Обычно с использованием $str[0] не возникает никаких проблем (и я уверен, что он намного быстрее, чем метод substr()).

Есть только одно предостережение в отношении обоих методов: они получат первый байт, а не первый символ. Это важно, если вы используете многобайтовые кодировки (например, UTF-8). Если вы хотите поддержать это, используйте mb_substr(). Возможно, в наши дни вы всегда должны предполагать многобайтовый ввод, так что это лучший вариант, но он будет немного медленнее.

person Hock    schedule 28.12.2009
comment
Учитывает ли PHP $ str [0], что могут быть символы длиной 2 байта? UTF и тому подобное? (хотя substr () с этим тоже не помогает!) - person Tomer W; 26.06.2013
comment
Если вы хотите быть сверхсверхбезопасным, вам следует использовать mb_substr($str, 0, 1, 'utf-8'), чтобы не обрезать многобайтовую строку. - person Vic; 28.08.2013
comment
Ссылка на документы: php.net / manual / en / - person biziclop; 17.09.2013
comment
Хотя это короче и его легче запомнить, чем substr($str, 0, 1), это сбивает с толку тех, кто читает код. - person trante; 02.11.2013
comment
Выбор между квадратными скобками и substr () в значительной степени является вопросом предпочтения, но имейте в виду, что результат будет другим при применении к пустой строке. Если $ s =, то $ s [] ===, но substr ($ s, 0, 1) === false. - person xtempore; 06.07.2014
comment
Если $ s =, то $ s [0] сгенерирует сообщение Notice: Uninitialized string offset: 0, тогда как substr ($ s, 0, 1) не будет. - person chris; 28.10.2014
comment
У меня проблема с такими массивами char. Поскольку мы можем получить доступ к $ str [0], но почему мы не можем получить доступ к foreach ($ str as $ c) ... - person Abhisek Malakar; 06.12.2014
comment
-1; хотя и достаточно расплывчато, чтобы не прямо ложно, утверждение, что строки можно рассматривать как массивы символов, довольно вводит в заблуждение; у них нет почти ничего общего, кроме того, что они индексируются с помощью индексов в стиле [0] или {0}. Функции работы с массивами не работают со строками (и наоборот), а специальный синтаксис для добавления к массивам ($some_array[] = $new_element) не работает со строками. - person Mark Amery; 12.03.2017
comment
Какие-либо доказательства концепции и цитирования для Строки можно рассматривать как массивы символов? Я не нашел функций массива, работающих для String !! РЕДАКТИРОВАТЬ: только что заметил, что @MarkAmery уже указал на это. Однако цитата все же нужна. - person Fr0zenFyr; 10.10.2017
comment
Можем ли мы использовать array_shift ($ string) для получения первого символа? - person Odin Thunder; 05.12.2017
comment
Нет, не можем :) - person Odin Thunder; 05.12.2017

Синтаксис {} устарел с PHP 5.3.0. Рекомендуются квадратные скобки.

person Michael Morton    schedule 28.12.2009
comment
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]. - person VolkerK; 29.12.2009
comment
@VolkerK: по предоставленной вами ссылке я заметил, что они удалили примечание в руководстве по PHP, которое оставили только: Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. Поэтому мне интересно, решили ли они, что использование {} больше НЕ устарело с PHP 6 - person Marco Demaio; 21.02.2012
comment
@MarcoDemaio Теперь ссылка говорит о том, что говорит Майкл Мортон. - person Tino; 21.02.2014
comment
не указывает на устаревание - действительно, сообщение об устаревании было удалено в версии 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/types/ - person VolkerK; 15.03.2017
comment
На сегодняшний день (10 мая 2018 г.) цитата из понравившегося Документы PHP: Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. Похоже, что этот синтаксис сохранится на некоторое время. - person Fr0zenFyr; 10.05.2018
comment
И он снова обновился. Теперь он устарел в PHP 7.4.0 и удален в 8.0.0. - person RobinHood70; 15.05.2021

Допустим, вам просто нужен первый символ из части $ _POST, давайте назовем его «тип». И этот $ _POST ['type'] в настоящее время является «Control». Если в этом случае вы используете $_POST['type'][0] или substr($_POST['type'], 0, 1), вы получите C обратно.

Однако, если клиентская сторона должна была изменить данные, которые они отправляют вам, например, с type на type[], а затем отправить 'Control' и 'Test' в качестве данных для этого массива, $_POST['type'][0] теперь вернет Control, а не C, тогда как substr($_POST['type'], 0, 1) будет просто просто потерпеть неудачу.

Так что да, могут возникнуть проблемы с использованием $str[0], но это зависит от окружающих обстоятельств.

person gattsbr    schedule 06.05.2013
comment
В качестве побочного примечания, чтобы обойти эту конкретную проблему, и в любом случае всегда следует выполнять проверку данных. if (true === is_string($_POST['type'])) - person Will B.; 12.08.2015

Я сомневаюсь только в том, насколько применим этот метод к многобайтовым строкам, но если это не вопрос, то я подозреваю, что вы покрыты. (В случае сомнений, mb_substr() кажется очевидным безопасным выбором.)

Однако с точки зрения общей картины я должен задаться вопросом, как часто вам нужно обращаться к n-му символу в строке, чтобы это стало ключевым соображением.

person John Parker    schedule 28.12.2009

Это будет зависеть от ресурсов, но вы можете запустить приведенный ниже сценарий и убедиться в этом сами;)

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

Некоторые ссылочные номера (на старой машине CoreDuo)

$ 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

Похоже, что использование операторов [] или {} более или менее одинаково.

person Willy Stadnick    schedule 30.01.2014
comment
Хороший тест! Некоторые цифры от 3-летнего Xeon: среднее микровремя с плавающей запятой с использованием array [] составляет 2,2427082061768E-7, среднее микропериод с плавающей запятой с использованием substr () составляет 3,9647579193115E-7, среднее микропериод с плавающей запятой с использованием array {} составляет 2,1522283554077E-7 - person Ellert van Koperen; 02.06.2016
comment
для точных измерений вам лучше сделать микропериод вне цикла и не смешивать разные подходы в одном цикле. - person PypeBros; 04.08.2016
comment
@PypeBros, не могли бы вы рассказать о преимуществах своего подхода и, возможно, поделиться кодом? Благодарность - person Willy Stadnick; 07.08.2016
comment
предполагая, что microtime() измеряет с точностью p, то есть microtime() - p < real time < microtime+p, выполнение before=mt(); 1000_testsA; after=mt() позволяет вычислить выполнение 1 итерации с точностью p / 1000. - person PypeBros; 09.08.2016
comment
отсутствие смешивания выполнения testA и testB в одних и тех же циклах означает, что вы способны обнаруживать, например, тот факт, что testB уничтожает кеш, а testA поддерживает кеширование. Когда они оба находятся в одном цикле, считается, что у них одинаковые тайминги, потому что testB загрязняет кеширование testA. - person PypeBros; 09.08.2016
comment
Точно так же я бы избегал генерации строк или случайных чисел в циклах тестирования и имел бы их готовыми в массиве поблизости. - person PypeBros; 09.08.2016
comment
-1; оставив в стороне сомнительный механизм синхронизации (было бы лучше рассчитать время для многих операций, чем для их одной за раз; я беспокоился, читая это, что только время, затраченное на выполнение вызова microtime(), будет составлять большую часть разницы во времени, хотя экспериментально это кажется неправдой), здесь нет причин беспокоиться о крошечной разнице в скорости. Это доли миллионной секунды; когда это когда-нибудь будет иметь значение? - person Mark Amery; 12.03.2017

Говоря простым смертным, я бы придерживался $str[0]. Насколько я понимаю, быстрее понять значение $str[0] с первого взгляда, чем substr($str, 0, 1). Вероятно, это зависит от предпочтений.

Что касается производительности, ну профиль профиля профиль. :) Или вы можете заглянуть в исходный код PHP ...

person Stephen    schedule 28.12.2009

В случае многобайтовых (unicode) строк использование str[0] может вызвать проблемы. mb_substr() - лучшее решение. Например:

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

Некоторые подробности здесь: Получить первый символ строки UTF-8

person Sergey Burish    schedule 16.10.2014
comment
Спасибо за это решение! если первый символ - юникод, [] работать не будет - person SunB; 24.03.2019

Я использовал это обозначение и раньше, без побочных эффектов и недоразумений. В этом есть смысл - в конце концов, строка - это просто массив символов.

person Kaleb Brasee    schedule 28.12.2009
comment
Нет, строка не является массивом символов (по крайней мере, поскольку PHP использует эти два термина). -1. - person Mark Amery; 12.03.2017
comment
@gattsbr внутренне они есть, но что касается модели, которую предоставляет PHP, это принципиально разные вещи. Доступ к смещению с использованием обозначения квадратных скобок - почти единственная операция, которая у них есть общая с массивами; строковые функции не работают с массивами, и наоборот, а синтаксис добавления массива ($arr[] = $new_element) не работает со строками. Таким образом, я не думаю, что представление строк как массивов символов полезно. - person Mark Amery; 13.03.2017
comment
@markamery лучше переписать руководство по php.net, чем включать такие мелкие технические детали. - person gattsbr; 13.03.2017

person    schedule
comment
-1; вопрос OP заключался в том, был ли этот синтаксис плохой практикой, и вы ответили ... повторением синтаксиса без каких-либо комментариев? Это не ответ. - person Mark Amery; 12.03.2017