Abrufen des ersten Zeichens einer Zeichenfolge mit $ str [0]

275

Ich möchte den ersten Buchstaben einer Zeichenfolge erhalten und habe festgestellt, dass dies $str[0]hervorragend funktioniert. Ich bin mir nur nicht sicher, ob dies eine "gute Praxis" ist, da diese Notation im Allgemeinen bei Arrays verwendet wird. Diese Funktion scheint nicht sehr gut dokumentiert zu sein, also wende ich mich an euch, um mir zu sagen, ob es in jeder Hinsicht in Ordnung ist, diese Notation zu verwenden.

Oder sollte ich mich einfach an den guten Alten halten substr($str, 0, 1)?

Außerdem habe ich festgestellt, dass geschweifte Klammern ( $str{0}) ebenfalls funktionieren. Was ist damit?

Tatu Ulmanen
quelle
5
plus 1 für das "gute alte Substrat ($ str, 0, 1)".
Santiago beendet SO

Antworten:

388

Ja. Zeichenfolgen können als Zeichenarrays angesehen werden. Der Zugriff auf eine Position eines Arrays erfolgt über den []Operator. Normalerweise gibt es überhaupt kein Problem bei der Verwendung $str[0](und ich bin mir ziemlich sicher, dass es viel schneller als die substr()Methode ist).

Bei beiden Methoden gibt es nur eine Einschränkung: Sie erhalten das erste Byte und nicht das erste Zeichen . Dies ist wichtig, wenn Sie Multibyte-Codierungen verwenden (z. B. UTF-8). Wenn Sie dies unterstützen möchten, verwenden Sie mb_substr(). Wahrscheinlich sollten Sie heutzutage immer von einer Multibyte-Eingabe ausgehen, daher ist dies die beste Option, aber sie wird etwas langsamer sein.

Sprunggelenk
quelle
7
Berücksichtigt PHP $ str [0], dass es 2Byte lange Zeichen geben kann? UTF und so? (obwohl substr () auch nicht hilft!)
Tomer W
77
Wenn Sie besonders sicher sein möchten, sollten mb_substr($str, 0, 1, 'utf-8')Sie dies tun, damit Sie keine Multibyte-Zeichenfolge abschneiden.
Vic
18
Obwohl dies kürzer und leichter zu merken ist substr($str, 0, 1), verwirrt dies, wer den Code liest.
Trante
10
Die Wahl zwischen eckigen Klammern und substr () ist weitgehend eine Frage der Präferenz. Beachten Sie jedoch, dass das Ergebnis unterschiedlich ist, wenn es auf eine leere Zeichenfolge angewendet wird. Wenn $ s = "", dann $ s [] === "", aber substr ($ s, 0, 1) === false.
xtempore
9
Wenn $ s = "", generiert $ s [0] einen "Hinweis: Nicht initialisierter String-Offset: 0", während substr ($ s, 0, 1) dies nicht tut.
Chris
46

Die Syntax {} ist ab PHP 5.3.0 veraltet. Eckige Klammern werden empfohlen.

Michael Morton
quelle
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: Unter dem von Ihnen angegebenen Link habe ich festgestellt, dass sie den Hinweis im PHP-Handbuch entfernt haben, den sie nur hinterlassen haben. Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose.Ich frage mich also, ob sie entschieden haben, dass die Verwendung ab {}PHP 6 NICHT mehr veraltet ist
Marco Demaio
1
@MarcoDemaio Der Link sagt jetzt, was MichaelMorton sagt.
Tino
1
"gibt keinen Hinweis auf Verfall" - In der Tat wurde die Verfallsmeldung in Revision 304518 entfernt - 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
Ab heute (10. Mai 18) ein Zitat aus den beliebten PHP-Dokumenten : Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. Diese Syntax scheint noch eine Weile zu bleiben.
Fr0zenFyr
25

Nehmen wir an, Sie möchten nur das erste Zeichen aus einem Teil von $ _POST, nennen wir es 'Typ'. Und dieses $ _POST ['Typ'] ist derzeit 'Kontrolle'. Wenn in diesem Fall, wenn Sie verwenden $_POST['type'][0], oder substr($_POST['type'], 0, 1)Sie werden Czurückkommen.

Wenn die Clientseite jedoch die Daten ändert, die sie Ihnen beispielsweise von typebis type[]sendet, und dann 'Control' und 'Test' als Daten für dieses Array sendet, $_POST['type'][0]wird dies jetzt zurückgegeben Controlund nicht einfach, Cwährend dies substr($_POST['type'], 0, 1)einfach fehlschlägt.

Ja, es kann ein Problem bei der Verwendung geben $str[0], aber das hängt von den Umgebungsbedingungen ab.

gattsbr
quelle
2
Als Randnotiz zur Umgehung dieses speziellen Problems und in jedem Fall sollte immer eine Datenvalidierung durchgeführt werden. if (true === is_string($_POST['type']))
Fyrye
13

Mein einziger Zweifel wäre, wie anwendbar diese Technik auf Multi-Byte-Strings wäre, aber wenn dies keine Überlegung ist, dann vermute ich, dass Sie abgedeckt sind. (Im Zweifelsfall mb_substr()scheint dies eine offensichtlich sichere Wahl zu sein.)

Aus einer Gesamtperspektive muss ich mich jedoch fragen, wie oft Sie auf das 'n'-te Zeichen in einer Zeichenfolge zugreifen müssen, damit dies eine wichtige Überlegung ist.

John Parker
quelle
9

Es hängt von den Ressourcen ab, aber Sie können das folgende Skript ausführen und sich selbst davon überzeugen;)

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

Einige Referenznummern (auf einem alten CoreDuo-Computer)

$ 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

Es scheint , dass die Verwendung []oder {}Betreiber mehr oder weniger das gleiche ist .

Willy Stadnick
quelle
2
Schöner Test! Einige Zahlen von einem 3 Jahre alten Xeon: Die durchschnittliche Float-Mikrozeit mit "array []" beträgt 2.2427082061768E-7. Die durchschnittliche Float-Mikrozeit mit "substr ()" beträgt 3.9647579193115E-7. Die durchschnittliche Float-Mikrozeit mit "array {}" beträgt 2.1522283554077E-7
Ellert van Koperen
Für genaue Messungen sollten Sie die Mikrozeit besser außerhalb der Schleife durchführen und nicht die verschiedenen Ansätze innerhalb derselben Schleife mischen.
PypeBros
1
Wenn Sie die Ausführung von testAund testBinnerhalb derselben Schleifen nicht mischen , können Sie beispielsweise die Tatsache erkennen, dass testBes sich um einen Cache-Killer handelt, während Sie testACache-freundlich sind. Wenn sie sich beide in derselben Schleife befinden, wird gemessen, dass sie aufgrund des Caching der testBverschmutzten Zeit die gleichen Timings haben testA.
PypeBros
1
In ähnlicher Weise würde ich vermeiden, Zeichenfolgen oder Zufälle innerhalb der Testschleifen zu generieren, und sie in einem Array in der Nähe bereithalten.
PypeBros
1
-1; Abgesehen von dem fragwürdigen Zeitmechanismus (es wäre besser, viele Operationen zeitlich zu planen, als sie einzeln zu messen) machte ich mir beim Lesen Sorgen, dass nur die Zeit, die für den microtime()Anruf benötigt wird, den größten Teil des Zeitunterschieds ausmachen würde, obwohl dies experimentell scheint um nicht wahr zu sein), gibt es hier keinen Grund, sich um den winzigen Geschwindigkeitsunterschied zu kümmern. Es ist ein Bruchteil einer Millionstel Sekunde; Wann wird das jemals eine Rolle spielen?
Mark Amery
6

Wenn ich nur als Sterblicher spreche, bleibe ich dabei $str[0]. Für mich ist es schneller, die Bedeutung von $str[0]auf einen Blick zu erfassen als substr($str, 0, 1). Dies läuft wahrscheinlich auf eine Frage der Präferenz hinaus.

Was die Leistung angeht, Profilprofil Profil. :) Oder Sie könnten in den PHP-Quellcode schauen ...

Stephen
quelle
6
$str = 'abcdef';
echo $str[0];                 // a
Jakir Hossain
quelle
6
-1; Die Frage des OP war, ob diese Syntax eine schlechte Praxis war, und Sie haben geantwortet, indem Sie ... die Syntax ohne Kommentar wiederholt haben? Dies ist keine Antwort.
Mark Amery
5

Bei Multibyte-Zeichenfolgen (Unicode-Zeichenfolgen) str[0]kann die Verwendung Probleme verursachen. mb_substr()ist eine bessere Lösung. Zum Beispiel:

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

Einige Details hier: Holen Sie sich das erste Zeichen der UTF-8-Zeichenfolge

Sergey Burish
quelle
Vielen Dank für diese Lösung! Wenn das erste Zeichen Unicode ist, funktioniert [] nicht
SunB
1

Ich habe diese Notation auch schon einmal verwendet, ohne schlechte Nebenwirkungen und ohne Missverständnisse. Es macht Sinn - eine Zeichenfolge besteht schließlich nur aus einer Reihe von Zeichen.

Kaleb Brasee
quelle
Nein, eine Zeichenfolge ist kein Array von Zeichen (zumindest da PHP diese beiden Begriffe verwendet). -1.
Mark Amery
@gattsbr intern sind sie, aber was das Modell betrifft, das PHP verfügbar macht, sind sie eine grundlegend andere Sache. Der Zugriff auf einen Offset mit eckiger Klammer ist so ziemlich die einzige Operation, die sie mit Arrays gemeinsam haben. Zeichenfolgenfunktionen funktionieren weder bei Arrays noch umgekehrt, und die Array-Append-Syntax ( $arr[] = $new_element) funktioniert nicht bei Zeichenfolgen. Daher halte ich es nicht für sinnvoll, Strings als Zeichenarrays zu verstehen.
Mark Amery
@markamery schreibt das php.net-Handbuch besser um, als eine so winzige Technik.
Gattsbr