Ottenere il primo carattere di una stringa con $ str [0]


276

Voglio ottenere la prima lettera di una stringa e ho notato che $str[0]funziona alla grande. Non sono sicuro che si tratti di una "buona pratica", poiché tale notazione viene generalmente utilizzata con le matrici. Questa funzione non sembra essere ben documentata, quindi mi rivolgo a voi ragazzi per dirmi se va bene, sotto tutti gli aspetti, usare questa notazione?

O dovrei semplicemente attenermi al buon vecchio substr($str, 0, 1)?

Inoltre, ho notato che anche le parentesi graffe ( $str{0}) funzionano. Cosa succede con quello?


5
più 1 per il "buon vecchio substrato ($ str, 0, 1)".
Santiago esce il

Risposte:


390

Sì. Le stringhe possono essere viste come array di caratteri e il modo per accedere a una posizione di un array è utilizzare l' []operatore. Di solito non c'è alcun problema nell'uso $str[0](e sono abbastanza sicuro che sia molto più veloce del substr()metodo).

C'è solo un avvertimento con entrambi i metodi: otterranno il primo byte , anziché il primo carattere . Ciò è importante se si utilizzano codifiche multibyte (come UTF-8). Se vuoi supportarlo, usa mb_substr(). Probabilmente, dovresti sempre assumere input multibyte in questi giorni, quindi questa è l' opzione migliore , ma sarà leggermente più lenta.


7
PHP $ str [0] tiene conto del fatto che possono esserci caratteri lunghi 2Byte? UTF e simili? (anche se substr () non aiuta neanche!)
Tomer W

77
Se vuoi essere super sicuro, dovresti andare avanti in mb_substr($str, 0, 1, 'utf-8')modo da non troncare una stringa multibyte.
Vic

18
Anche se questo è più breve ed è più facile da ricordare substr($str, 0, 1), questo confonde chi legge il codice.
trante,

10
La scelta tra parentesi quadre e substr () è in gran parte una questione di preferenza, ma tieni presente che il risultato è diverso se applicato a una stringa vuota. Se $ s = "" allora $ s [] === "", ma substr ($ s, 0, 1) === falso.
xtempore,

9
Se $ s = "" allora $ s [0] genererà un "Avviso: Offset stringa non inizializzato: 0" mentre il substr ($ s, 0, 1) no.
chris,

46

La sintassi {} è obsoleta a partire da PHP 5.3.0. Si raccomandano parentesi quadre.


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: al link che hai fornito ho notato che hanno rimosso la nota sul manuale di PHP che hanno lasciato solo: Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose.Quindi mi chiedo se hanno deciso che l'utilizzo {}NON è più deprecato a partire da PHP 6
Marco Demaio

1
@MarcoDemaio Il link ora dice ciò che dice MichaelMorton.
Tino,

1
"non fornisce alcuna indicazione di deprecazione" - In effetti, il messaggio di deprecazione è stato rimosso nella revisione 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/…
VolkerK

A partire da oggi (10 maggio 18), una citazione dai piacevoli documenti di PHP : Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. sembra che questa sintassi rimarrà per un po '.
Fr0zenFir

25

Diciamo che vuoi solo il primo carattere da una parte di $ _POST, chiamiamolo 'tipo'. E che $ _POST ['type'] è attualmente 'Control'. Se in questo caso, se si utilizza $_POST['type'][0], o substr($_POST['type'], 0, 1)si otterrà Cindietro.

Tuttavia, se il lato client dovesse modificare i dati che viene inviato, da typea type[]per esempio, e quindi inviare 'Control' e 'Test', come i dati relativi a questa matrice, $_POST['type'][0]sarà ora tornare Controlpiuttosto che Cmentre substr($_POST['type'], 0, 1)si limiterà semplicemente fallire.

Quindi sì, potrebbe esserci un problema con l'utilizzo $str[0], ma ciò dipende dalle circostanze circostanti.


2
Come nota a margine per aggirare questo particolare problema e in entrambi i casi si dovrebbe sempre eseguire la convalida dei dati. if (true === is_string($_POST['type']))
Fyrye,

13

Il mio unico dubbio sarebbe quanto applicabile sarebbe questa tecnica su stringhe multi-byte, ma se questa non è una considerazione, allora sospetto che tu sia coperto. (In caso di dubbio, mb_substr()sembra una scelta ovviamente sicura.)

Tuttavia, dal punto di vista generale, devo chiedermi quanto spesso è necessario accedere all'ennesimo carattere in una stringa perché questa sia una considerazione chiave.


9

Varia in base alle risorse, ma potresti eseguire lo script sotto e vedere di persona;)

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

Alcuni numeri di riferimento (su una vecchia macchina 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

Sembra che l'uso degli operatori []o {}sia più o meno lo stesso.


2
Bel test! Alcuni numeri di un Xeon di 3 anni: la media dei microtime float usando "array []" è 2.2427082061768E-7 la media dei microtime float usando "substr ()" è 3.9647579193115E-7 la media dei microtime float usando "array {}" è 2.1522283554077E-7
Ellert van Koperen,

per misurazioni accurate, dovresti imitare meglio i microtime fuori dal ciclo e non mescolare i diversi approcci all'interno dello stesso circuito.
PypeBros,

1
non mescolare l'esecuzione di testAe testBall'interno degli stessi loop significa che si è in grado di rilevare, ad esempio, il fatto che testBè un killer della testAcache mentre è compatibile con la cache. Quando sono entrambi nello stesso loop, vengono misurati per avere gli stessi tempi perché la cache testBinquinata testA.
PypeBros,

1
allo stesso modo, eviterei di generare stringhe o randoms all'interno dei circuiti di prova e di averli pronti in un array vicino.
PypeBros,

1
-1; lasciando da parte il meccanismo di temporizzazione discutibile (sarebbe meglio programmare molte operazioni piuttosto che cronometrarle una alla volta; mi preoccupavo di leggere questo che solo il tempo impiegato a fare la microtime()chiamata avrebbe compensato la maggior parte della differenza di tempo, anche se a livello sperimentale sembra per non essere vero), non c'è motivo di preoccuparsi della piccola differenza di velocità qui. È una frazione di milionesimo di secondo; quando mai questo avrà importanza?
Mark Amery,

6

Parlando come un semplice mortale, mi atterrei $str[0]. Per quanto mi riguarda, è più veloce cogliere il significato $str[0]a colpo d'occhio che substr($str, 0, 1). Questo probabilmente si riduce a una questione di preferenza.

Per quanto riguarda le prestazioni, beh, profilo profilo profilo. :) Oppure potresti scrutare il codice sorgente di PHP ...


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

6
-1; la domanda del PO era se questa sintassi fosse una cattiva pratica, e tu hai risposto ... ripetendo la sintassi, senza alcun commento? Questa non è una risposta
Mark Amery,


1

Ho usato anche quella notazione prima, senza effetti collaterali negativi e incomprensioni. Ha senso: una stringa è solo una matrice di caratteri, dopo tutto.


No, una stringa non è un array di caratteri (almeno poiché PHP usa questi due termini). -1.
Mark Amery,


Lo sono @gattsbr internamente, ma per quanto riguarda il modello esposto da PHP, sono fondamentalmente diversi. Accedere a un offset usando la notazione parentesi quadra è praticamente l'unica operazione che hanno in comune con le matrici; le funzioni di stringa non funzionano su array, né viceversa, e la sintassi di aggiunta dell'array ( $arr[] = $new_element) non funziona su stringhe. Pertanto, non penso che concepire le stringhe come array di caratteri sia utile.
Mark Amery,

È meglio che @markamery riscriva il manuale di php.net e includa un tecnicismo così minuscolo.
gattsbr,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.