2009-03-06 3 views
105

Il modo standard di PHP per verificare se una stringa $str termina con una stringa $test è:Qual è il test più efficiente se una stringa PHP termina con un'altra stringa?

$endsWith = substr($str, -strlen($test)) == $test 

È questo il modo più veloce?

+2

analogo: http://stackoverflow.com/questions/834303/php-startswith- and-endswith-functions – trante

+0

Potresti trovare ['s ($ str) -> endsWith ($ test)'] (https://github.com/delight-im/PHP-Str/blob/8fd0c608d5496d43adaa899642c1cce047e076dc/src/Str. php # L117) o ['s ($ str) -> endsWithIgnoreCase ($ test)'] (https://github.com/delight-im/PHP-Str/blob/8fd0c608d5496d43adaa899642c1cce047e076dc/src/Str.php#L131) utile, come trovato in [questa libreria standalone] (https://github.com/delight-im/PHP-Str). – caw

risposta

132

Ciò che Assaf ha detto è corretto. C'è una funzione incorporata in PHP per fare esattamente questo.

substr_compare($str, $test, strlen($str)-strlen($test), strlen($test)) === 0; 

Se $test è più lungo di $str PHP darà un avvertimento, quindi è necessario verificare la presenza di quella prima.

function endswith($string, $test) { 
    $strlen = strlen($string); 
    $testlen = strlen($test); 
    if ($testlen > $strlen) return false; 
    return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0; 
} 
+0

Bello. Sembrerebbe che il confronto sul posto sia più veloce di substr(), come ha rilevato Assaf. –

+2

La risposta di mcrumley è interessante, ma dovrebbe usare '===' invece di '=='. '===' è più severo e di solito fa quello che vuoi, mentre '==' può portare a brutte sorprese. Il terzo snippet di codice di mcrumley è corretto, ma i primi due non lo sono. substr_compare() restituisce false in alcuni casi di errore. In PHP, false == 0, quindi i frammenti di codice segnalerebbero che la stringa è stata trovata. Con ===, questo non succede. –

+0

Oggi mi sono imbattuto in un bug che interromperà la soluzione fornita da PHP 5.5.11 in poi. https://bugs.php.net/bug.php?id=67043 – user2180613

7

Dipende dal tipo di efficienza che ti interessa.

La versione utilizza più memoria a causa della copia extra dall'uso di substr.

Una versione alternativa potrebbe cercare la stringa originale per l'ultima occorrenza della sottostringa senza fare una copia, ma probabilmente sarebbe più lenta a causa di più test.

Probabilmente il modo più efficiente è di eseguire il loop char-by-char dalla posizione -sterlen (test) fino alla fine della stringa e confrontare. Questa è la quantità minima di confronti che puoi sperare di fare e non c'è quasi nessuna memoria extra usata.

4

Un altro modo sarebbe quello di utilizzare il strrpos function:

strrpos($str, $test) == strlen($str) - strlen($test) 

Ma non è più veloce.

0

Sto pensando le funzioni inverse come strrchr() aiuterebbe abbinare la fine della stringa il più veloce.

63

Questo metodo è un po 'più piccolo di memoria-costoso, ma è più veloce:

stripos(strrev($haystack), $reversed_needle) === 0; 

Questa è la cosa migliore quando si sa esattamente che cosa è l'ago, in modo da poter hard-code è invertita. Se si inverte l'ago in modo programmatico, diventa più lento rispetto al metodo precedente.

+0

Questo è semplicemente così intelligente! –

+0

+1 per originalità! –

+2

-1 Dubito seriamente che sia più veloce, ed è difficile (interessante ma non di solito utile). Se il pagliaio * non termina con l'ago, 'stripos' itererà l'intera stringa nel caso peggiore mentre' substr_compare' confronterà al massimo la lunghezza dell'ago. Sì, 'substr_compare' richiede il calcolo della lunghezza del pagliaio (e dell'ago molto più piccolo), ma questo metodo richiede che * e * lo copi completamente, e possibilmente convertendo l'intera cosa in minuscolo per l'avvio. –

7

Ecco un modo semplice per controllare se una stringa termina con un altro, dando strpos un offset a destra dove dovrebbe essere trovata la stringa:

function stringEndsWith($whole, $end) 
{ 
    return (strpos($whole, $end, strlen($whole) - strlen($end)) !== false); 
} 

Semplice, e credo che questo sarà il lavoro in PHP 4.

2

spero che la risposta qui sotto può essere efficiente e anche semplice:

$content = "The main string to search"; 
$search = "search"; 
//For compare the begining string with case insensitive. 
if(stripos($content, $search) === 0) echo 'Yes'; 
else echo 'No'; 

//For compare the begining string with case sensitive. 
if(strpos($content, $search) === 0) echo 'Yes'; 
else echo 'No'; 

//For compare the ending string with case insensitive. 
if(stripos(strrev($content), strrev($search)) === 0) echo 'Yes'; 
else echo 'No'; 

//For compare the ending string with case sensitive. 
if(strpos(strrev($content), strrev($search)) === 0) echo 'Yes'; 
else echo 'No'; 
-1

Questo è puro PHP, senza chiamare funzione esterna s, ad eccezione di strlen.

function endsWith ($ends, $string) 
{ 
    $strLength = strlen ($string); 
    $endsLength = strlen ($ends); 
    for ($i = 0; $i < $endsLength; $i++) 
    { 
     if ($string [$strLength - $i - 1] !== $ends [$i]) 
      return false; 
    } 
    return true; 
} 
35
$endsWith = substr_compare($str, $test, -strlen($test)) === 0 

Negative offset "avvia il conteggio dalla fine della stringa".

+3

IMO è uno dei migliori dalle soluzioni fornite –

+4

Dovrebbe essere la risposta accettata – FrancescoMM

+0

+200 se potessi. L'intuizione chiave qui è che usando una lunghezza negativa si ottiene la parte finale della stringa. Si potrebbe anche usare substr con la lunghezza -ve e fare un == contro $ test. Le altre risposte sono scarse. – Nick

1

Non so se questo è veloce o no, ma per un singolo test di carattere, questi lavori, anche:

(array_pop(str_split($string)) === $test) ? true : false; 
($string[strlen($string)-1] === $test) ? true : false; 
(strrev($string)[0] === $test) ? true : false;