para - Las funciones startsWith() y endsWith() en PHP
php startswith (30)
La solución más rápida con los extremos ():
# Checks if a string ends in a string
function endsWith($haystack, $needle) {
return substr($haystack,-strlen($needle))===$needle;
}
Punto de referencia:
# This answer
function endsWith($haystack, $needle) {
return substr($haystack,-strlen($needle))===$needle;
}
# Accepted answer
function endsWith2($haystack, $needle) {
$length = strlen($needle);
return $length === 0 ||
(substr($haystack, -$length) === $needle);
}
# Second most-voted answer
function endsWith3($haystack, $needle) {
// search forward starting from end minus needle length characters
if ($needle === '''') {
return true;
}
$diff = /strlen($haystack) - /strlen($needle);
return $diff >= 0 && strpos($haystack, $needle, $diff) !== false;
}
# Regex answer
function endsWith4($haystack, $needle) {
return preg_match(''/'' . preg_quote($needle, ''/'') . ''$/'', $haystack);
}
function timedebug() {
$test = 10000000;
$time1 = microtime(true);
for ($i=0; $i < $test; $i++) {
$tmp = endsWith(''TestShortcode'', ''Shortcode'');
}
$time2 = microtime(true);
$result1 = $time2 - $time1;
for ($i=0; $i < $test; $i++) {
$tmp = endsWith2(''TestShortcode'', ''Shortcode'');
}
$time3 = microtime(true);
$result2 = $time3 - $time2;
for ($i=0; $i < $test; $i++) {
$tmp = endsWith3(''TestShortcode'', ''Shortcode'');
}
$time4 = microtime(true);
$result3 = $time4 - $time3;
for ($i=0; $i < $test; $i++) {
$tmp = endsWith4(''TestShortcode'', ''Shortcode'');
}
$time5 = microtime(true);
$result4 = $time5 - $time4;
echo $test.''x endsWith: ''.$result1.'' seconds # This answer<br>'';
echo $test.''x endsWith2: ''.$result4.'' seconds # Accepted answer<br>'';
echo $test.''x endsWith3: ''.$result2.'' seconds # Second most voted answer<br>'';
echo $test.''x endsWith4: ''.$result3.'' seconds # Regex answer<br>'';
exit;
}
timedebug();
Resultados de referencia:
10000000x endsWith: 1.5760900974274 seconds # This answer
10000000x endsWith2: 3.7102129459381 seconds # Accepted answer
10000000x endsWith3: 1.8731069564819 seconds # Second most voted answer
10000000x endsWith4: 2.1521229743958 seconds # Regex answer
¿Cómo puedo escribir dos funciones que tomarían una cadena y devolverían si comienza con el carácter / cadena especificada o termina con ella?
Por ejemplo:
$str = ''|apples}'';
echo startsWith($str, ''|''); //Returns true
echo endsWith($str, ''}''); //Returns true
¿Por qué no lo siguiente?
//How to check if a string begins with another string
$haystack = "valuehaystack";
$needle = "value";
if (strpos($haystack, $needle) === 0){
echo "Found " . $needle . " at the beginning of " . $haystack . "!";
}
Salida:
Valor encontrado al comienzo de valuehaystack!
Tenga en cuenta que el strpos
devolverá falso si no se encontró la aguja en el pajar, y devolverá 0 si, y solo si, se encontró la aguja en el índice 0 (al principio, también conocido).
Y aquí termina con:
$haystack = "valuehaystack";
$needle = "haystack";
//If index of the needle plus the length of the needle is the same length as the entire haystack.
if (strpos($haystack, $needle) + strlen($needle) === strlen($haystack)){
echo "Found " . $needle . " at the end of " . $haystack . "!";
}
En este escenario no hay necesidad de una función startsWith () como
(strpos($stringToSearch, $doesItStartWithThis) === 0)
devolverá verdadero o falso con precisión.
Parece extraño, es así de simple, con todas las funciones salvajes que se ejecutan aquí.
Actualizado 23-Ago-2016
Funciones
function substr_startswith($haystack, $needle) {
return substr($haystack, 0, strlen($needle)) === $needle;
}
function preg_match_startswith($haystack, $needle) {
return preg_match(''~'' . preg_quote($needle, ''~'') . ''~A'', $haystack) > 0;
}
function substr_compare_startswith($haystack, $needle) {
return substr_compare($haystack, $needle, 0, strlen($needle)) === 0;
}
function strpos_startswith($haystack, $needle) {
return strpos($haystack, $needle) === 0;
}
function strncmp_startswith($haystack, $needle) {
return strncmp($haystack, $needle, strlen($needle)) === 0;
}
function strncmp_startswith2($haystack, $needle) {
return $haystack[0] === $needle[0]
? strncmp($haystack, $needle, strlen($needle)) === 0
: false;
}
Pruebas
echo ''generating tests'';
for($i = 0; $i < 100000; ++$i) {
if($i % 2500 === 0) echo ''.'';
$test_cases[] = [
random_bytes(random_int(1, 7000)),
random_bytes(random_int(1, 3000)),
];
}
echo "done!/n";
$functions = [''substr_startswith'', ''preg_match_startswith'', ''substr_compare_startswith'', ''strpos_startswith'', ''strncmp_startswith'', ''strncmp_startswith2''];
$results = [];
foreach($functions as $func) {
$start = microtime(true);
foreach($test_cases as $tc) {
$func(...$tc);
}
$results[$func] = (microtime(true) - $start) * 1000;
}
asort($results);
foreach($results as $func => $time) {
echo "$func: " . number_format($time, 1) . " ms/n";
}
Resultados (PHP 7.0.9)
(Ordenado de más rápido a más lento)
strncmp_startswith2: 40.2 ms
strncmp_startswith: 42.9 ms
substr_compare_startswith: 44.5 ms
substr_startswith: 48.4 ms
strpos_startswith: 138.7 ms
preg_match_startswith: 13,152.4 ms
Resultados (PHP 5.3.29)
(Ordenado de más rápido a más lento)
strncmp_startswith2: 477.9 ms
strpos_startswith: 522.1 ms
strncmp_startswith: 617.1 ms
substr_compare_startswith: 706.7 ms
substr_startswith: 756.8 ms
preg_match_startswith: 10,200.0 ms
Aquí hay dos funciones que no introducen una cadena temporal, que podría ser útil cuando las agujas son sustancialmente grandes:
function startsWith($haystack, $needle)
{
return strncmp($haystack, $needle, strlen($needle)) === 0;
}
function endsWith($haystack, $needle)
{
return $needle === '''' || substr_compare($haystack, $needle, -strlen($needle)) === 0;
}
Aquí hay una versión segura de múltiples bytes de la respuesta aceptada, funciona bien para cadenas UTF-8:
function startsWith($haystack, $needle)
{
$length = mb_substr($needle, ''UTF-8'');
return (mb_substr($haystack, 0, $length, ''UTF-8'') === $needle);
}
function endsWith($haystack, $needle)
{
$length = mb_strlen($needle, ''UTF-8'');
return $length === 0 ||
(mb_substr($haystack, -$length, $length, ''UTF-8'') === $needle);
}
Es posible utilizar strrpos
y strpos
para verificar el inicio y el final con respectivamente.
Tenga en cuenta que el uso de strrpos
para verificar comienza con y strpos
para verificar los extremos regresará tan pronto como sea posible en lugar de revisar toda la cadena hasta el final. Además, esta solución no crea una cadena temporal. Considere explicar la razón antes de votar abajo. El hecho de que un imbécil en el DWTF no entienda cómo funciona esta función o piense que solo hay una solución no significa que esta respuesta sea incorrecta.
function startsWith($haystack, $needle) {
// search backwards starting from haystack length characters from the end
return $needle === ''''
|| strrpos($haystack, $needle, -strlen($haystack)) !== false;
}
function endsWith($haystack, $needle) {
// search forward starting from end minus needle length characters
if ($needle === '''') {
return true;
}
$diff = /strlen($haystack) - /strlen($needle);
return $diff >= 0 && strpos($haystack, $needle, $diff) !== false;
}
Pruebas y resultados ( comparar con esto ):
startsWith(''abcdef'', ''ab'') -> true
startsWith(''abcdef'', ''cd'') -> false
startsWith(''abcdef'', ''ef'') -> false
startsWith(''abcdef'', '''') -> true
startsWith('''', ''abcdef'') -> false
endsWith(''abcdef'', ''ab'') -> false
endsWith(''abcdef'', ''cd'') -> false
endsWith(''abcdef'', ''ef'') -> true
endsWith(''abcdef'', '''') -> true
endsWith('''', ''abcdef'') -> false
Nota: las funciones strncmp
y substr_compare
superarán esta función.
Espero que la siguiente respuesta sea eficiente y simple:
$content = "The main string to search";
$search = "T";
//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'';
Esta pregunta ya tiene muchas respuestas, pero en algunos casos puede conformarse con algo más simple que todos ellos. Si la cadena que está buscando es conocida (codificada), puede usar expresiones regulares sin ninguna cita, etc.
Compruebe si una cadena comienza con ''ABC'':
preg_match(''/^ABC/'', $myString); // "^" here means beginning of string
termina con ''ABC'':
preg_match(''/ABC$/'', $myString); // "$" here means end of string
En mi caso simple, quería comprobar si una cadena termina con una barra:
preg_match(''#/$#'', $myPath); // Use "#" as delimiter instead of escaping slash
La ventaja: ya que es muy corto y simple, no tiene que definir una función (como endsWith()
) como se muestra arriba.
Pero, de nuevo, esto no es una solución para cada caso, solo este muy específico.
Esto puede funcionar
function startsWith($haystack, $needle) {
return substr($haystack, 0, strlen($needle)) == $needle;
}
Fuente: https://.com/a/4419658
Generalmente termino yendo con una biblioteca como underscore-php estos días.
require_once("vendor/autoload.php"); //use if needed
use Underscore/Types/String;
$str = "there is a string";
echo( String::startsWith($str, ''the'') ); // 1
echo( String::endsWith($str, ''ring'')); // 1
La biblioteca está llena de otras funciones útiles.
La answer de es increíblemente completa, pero, desafortunadamente, el punto de referencia proporcionado tiene una supervisión muy importante y perjudicial.
Debido a que cada byte en las agujas y pajares es completamente aleatorio, la probabilidad de que un par de aguja-pajar difiera en el primer byte es 99. 609375%, lo que significa que, en promedio, aproximadamente 99609 de los 100000 pares serán diferentes en el primer byte. . En otras palabras, el punto de referencia está fuertemente startswith
hacia el startswith
implementaciones que comprueban explícitamente el primer byte, como hace strncmp_startswith2
.
Si el bucle generador de prueba se implementa de la siguiente manera:
echo ''generating tests'';
for($i = 0; $i < 100000; ++$i) {
if($i % 2500 === 0) echo ''.'';
$haystack_length = random_int(1, 7000);
$haystack = random_bytes($haystack_length);
$needle_length = random_int(1, 3000);
$overlap_length = min(random_int(0, $needle_length), $haystack_length);
$needle = ($needle_length > $overlap_length) ?
substr($haystack, 0, $overlap_length) . random_bytes($needle_length - $overlap_length) :
substr($haystack, 0, $needle_length);
$test_cases[] = [$haystack, $needle];
}
echo " done!<br />";
Los resultados de referencia cuentan una historia ligeramente diferente:
strncmp_startswith: 223.0 ms
substr_startswith: 228.0 ms
substr_compare_startswith: 238.0 ms
strncmp_startswith2: 253.0 ms
strpos_startswith: 349.0 ms
preg_match_startswith: 20,828.7 ms
Por supuesto, este punto de referencia todavía puede no ser perfectamente imparcial, pero prueba la eficiencia de los algoritmos cuando se les da agujas parcialmente coincidentes también.
La expresión regular funciona arriba, pero con los otros ajustes también sugeridos anteriormente:
function startsWith($needle, $haystack) {
return preg_match(''/^'' . preg_quote($needle, ''/'') . ''/'', $haystack);
}
function endsWith($needle, $haystack) {
return preg_match(''/'' . preg_quote($needle, ''/'') . ''$/'', $haystack);
}
La función substr
puede devolver false
en muchos casos especiales, por lo que aquí está mi versión, que trata estos problemas:
function startsWith( $haystack, $needle ){
return $needle === ''''.substr( $haystack, 0, strlen( $needle )); // substr''s false => empty string
}
function endsWith( $haystack, $needle ){
$len = strlen( $needle );
return $needle === ''''.substr( $haystack, -$len, $len ); // ! len=0
}
Pruebas ( true
significa bueno):
var_dump( startsWith('''',''''));
var_dump( startsWith(''1'',''''));
var_dump(!startsWith('''',''1''));
var_dump( startsWith(''1'',''1''));
var_dump( startsWith(''1234'',''12''));
var_dump(!startsWith(''1234'',''34''));
var_dump(!startsWith(''12'',''1234''));
var_dump(!startsWith(''34'',''1234''));
var_dump(''---'');
var_dump( endsWith('''',''''));
var_dump( endsWith(''1'',''''));
var_dump(!endsWith('''',''1''));
var_dump( endsWith(''1'',''1''));
var_dump(!endsWith(''1234'',''12''));
var_dump( endsWith(''1234'',''34''));
var_dump(!endsWith(''12'',''1234''));
var_dump(!endsWith(''34'',''1234''));
Además, la función substr_compare
también vale la pena mirar. http://www.php.net/manual/en/function.substr-compare.php
Me doy cuenta de que esto se ha terminado, pero es posible que desee ver strncmp ya que le permite comparar la longitud de la cadena, por lo que:
function startsWith($haystack, $needle, $case=true) {
if ($case)
return strncasecmp($haystack, $needle, strlen($needle)) == 0;
else
return strncmp($haystack, $needle, strlen($needle)) == 0;
}
Si está seguro de que las cadenas no están vacías, si se enfoca en los inicios, al agregar una prueba en el primer char, antes de la comparación, el strlen, etc.
function startswith5b($haystack, $needle) {
return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;
}
De alguna manera es (20% -30%) más rápido. Agregar otra prueba de char, como $ haystack {1} === $ needle {1} no parece acelerar mucho las cosas, incluso puede disminuir la velocidad.
===
parece más rápido que ==
operador condicional (a)?b:c
parece más rápido que if(a) b; else c;
if(a) b; else c;
Para aquellos que preguntan "¿por qué no usar strpos?" Llamando a otras soluciones "trabajo innecesario"
strpos es rápido, pero no es la herramienta adecuada para este trabajo.
Para entender, aquí hay una pequeña simulación como ejemplo:
Search a12345678c inside bcdefga12345678xbbbbb.....bbbbba12345678c
¿Qué hace la computadora "adentro"?
With strccmp, etc...
is a===b? NO
return false
With strpos
is a===b? NO -- iterating in haysack
is a===c? NO
is a===d? NO
....
is a===g? NO
is a===g? NO
is a===a? YES
is 1===1? YES -- iterating in needle
is 2===3? YES
is 4===4? YES
....
is 8===8? YES
is c===x? NO: oh God,
is a===1? NO -- iterating in haysack again
is a===2? NO
is a===3? NO
is a===4? NO
....
is a===x? NO
is a===b? NO
is a===b? NO
is a===b? NO
is a===b? NO
is a===b? NO
is a===b? NO
is a===b? NO
...
... may many times...
...
is a===b? NO
is a===a? YES -- iterating in needle again
is 1===1? YES
is 2===3? YES
is 4===4? YES
is 8===8? YES
is c===c? YES YES YES I have found the same string! yay!
was it at position 0? NOPE
What you mean NO? So the string I found is useless? YEs.
Damn.
return false
Suponiendo que strlen no itera toda la cadena (pero incluso en ese caso) esto no es conveniente en absoluto.
Si la velocidad es importante para ti, intenta esto (creo que es el método más rápido)
Funciona solo para cadenas y si $ haystack es solo 1 caracter
function startsWithChar($needle, $haystack)
{
return ($needle[0] === $haystack);
}
function endsWithChar($needle, $haystack)
{
return ($needle[strlen($needle) - 1] === $haystack);
}
$str=''|apples}'';
echo startsWithChar($str,''|''); //Returns true
echo endsWithChar($str,''}''); //Returns true
echo startsWithChar($str,''=''); //Returns false
echo endsWithChar($str,''#''); //Returns false
Todas las respuestas hasta ahora parecen realizar un montón de trabajo innecesario, strlen calculations
, string allocations (substr)
, etc. Las ''strpos''
y ''stripos''
devuelven el índice de la primera aparición de $needle
en $haystack
:
function startsWith($haystack,$needle,$case=true)
{
if ($case)
return strpos($haystack, $needle, 0) === 0;
return stripos($haystack, $needle, 0) === 0;
}
function endsWith($haystack,$needle,$case=true)
{
$expectedPosition = strlen($haystack) - strlen($needle);
if ($case)
return strrpos($haystack, $needle, 0) === $expectedPosition;
return strripos($haystack, $needle, 0) === $expectedPosition;
}
Unas líneas cortas y fáciles de entender sin expresiones regulares.
startsWith () es sencillo.
function startsWith($haystack, $needle) {
return (strpos($haystack, $needle) === 0);
}
endsWith () usa el strrev () ligeramente sofisticado y lento:
function endsWith($haystack, $needle) {
return (strpos(strrev($haystack), strrev($needle)) === 0);
}
en breve:
function startsWith($str, $needle){
return substr($str, 0, strlen($needle)) === $needle;
}
function endsWith($str, $needle){
$length = strlen($needle);
return !$length || substr($str, - $length) === $needle;
}
Basado en la respuesta de James Black, aquí están sus finales Con la versión:
function startsWith($haystack, $needle, $case=true) {
if ($case)
return strncmp($haystack, $needle, strlen($needle)) == 0;
else
return strncasecmp($haystack, $needle, strlen($needle)) == 0;
}
function endsWith($haystack, $needle, $case=true) {
return startsWith(strrev($haystack),strrev($needle),$case);
}
Nota: He cambiado la parte if-else por la función startsWith de James Black, porque strncasecmp es en realidad la versión de strncmp que no distingue mayúsculas y minúsculas.
Lo haria asi
function startWith($haystack,$needle){
if(substr($haystack,0, strlen($needle))===$needle)
return true;
}
function endWith($haystack,$needle){
if(substr($haystack, -strlen($needle))===$needle)
return true;
}
Sólo una recomendación:
function startsWith($haystack,$needle) {
if($needle==="") return true;
if($haystack[0]<>$needle[0]) return false;
if(substr_compare($haystack,$needle,0,strlen($needle))==0) return true;
return false;
}
Esa línea adicional, comparando el primer carácter de las cadenas, puede hacer que el caso falso regrese inmediatamente , por lo tanto, hacer que muchas de sus comparaciones sean mucho más rápidas (7 veces más rápido cuando lo medí). En el caso real, usted no paga virtualmente ningún precio en rendimiento por esa única línea, por lo que creo que vale la pena incluirla. (Además, en la práctica, cuando prueba muchas cadenas para un segmento de inicio específico, la mayoría de las comparaciones fallarán, ya que en un caso típico está buscando algo).
También puedes usar expresiones regulares:
function endsWith($haystack, $needle, $case=true) {
return preg_match("/.*{$needle}$/" . (($case) ? "" : "i"), $haystack);
}
Aquí hay una solución eficiente para PHP 4. Puede obtener resultados más rápidos si usa PHP 5 usando en substr_compare
lugar de strcasecmp(substr(...))
.
function stringBeginsWith($haystack, $beginning, $caseInsensitivity = false)
{
if ($caseInsensitivity)
return strncasecmp($haystack, $beginning, strlen($beginning)) === 0;
else
return strncmp($haystack, $beginning, strlen($beginning)) === 0;
}
function stringEndsWith($haystack, $ending, $caseInsensitivity = false)
{
if ($caseInsensitivity)
return strcasecmp(substr($haystack, strlen($haystack) - strlen($ending)), $haystack) === 0;
else
return strpos($haystack, $ending, strlen($haystack) - strlen($ending)) !== false;
}
Muchas de las respuestas anteriores funcionarán igual de bien. Sin embargo, es posible que esto sea lo más breve que pueda y haga que haga lo que desee. Solo dices que te gustaría que "vuelva a ser verdadero". Así que he incluido soluciones que devuelven boolean true / false y textual true / false.
// boolean true/false
function startsWith($haystack, $needle)
{
return strpos($haystack, $needle) === 0 ? 1 : 0;
}
function endsWith($haystack, $needle)
{
return stripos($haystack, $needle) === 0 ? 1 : 0;
}
// textual true/false
function startsWith($haystack, $needle)
{
return strpos($haystack, $needle) === 0 ? ''true'' : ''false'';
}
function endsWith($haystack, $needle)
{
return stripos($haystack, $needle) === 0 ? ''true'' : ''false'';
}
No estoy seguro de por qué esto es tan difícil para las personas. Substr hace un gran trabajo y es eficiente, ya que no es necesario buscar en toda la cadena si no coincide.
Además, como no estoy verificando valores enteros sino comparando cadenas, no necesariamente tengo que preocuparme por el estricto caso ===. Sin embargo, === es un buen hábito para entrar.
function startsWith($haystack,$needle) {
substring($haystack,0,strlen($needle)) == $needle) { return true; }
return false;
}
function endsWith($haystack,$needle) {
if(substring($haystack,-strlen($needle)) == $needle) { return true; }
return false;
}
O incluso mejor optimizado.
function startsWith($haystack,$needle) {
return substring($haystack,0,strlen($needle)) == $needle);
}
function endsWith($haystack,$needle) {
return substring($haystack,-strlen($needle)) == $needle);
}
$ends_with = strrchr($text, ''.''); // Ends with dot
$start_with = (0 === strpos($text, ''.'')); // Starts with dot
function startsWith($haystack, $needle)
{
$length = strlen($needle);
return (substr($haystack, 0, $length) === $needle);
}
function endsWith($haystack, $needle)
{
$length = strlen($needle);
if ($length == 0) {
return true;
}
return (substr($haystack, -$length) === $needle);
}
Use esto si no quiere usar una expresión regular.
function startsWith($haystack, $needle, $case = true) {
if ($case) {
return (strcmp(substr($haystack, 0, strlen($needle)), $needle) === 0);
}
return (strcasecmp(substr($haystack, 0, strlen($needle)), $needle) === 0);
}
function endsWith($haystack, $needle, $case = true) {
if ($case) {
return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);
}
return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);
}
Crédito a :