Question Les fonctions startsWith () et endsWith () en PHP


Comment puis-je écrire deux fonctions qui prendraient une chaîne et retourneraient si elle commence par le caractère / la chaîne spécifié ou se termine avec elle?

Par exemple:

$str = '|apples}';

echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true

1215
2018-05-07 12:14


origine


Réponses:


function startsWith($haystack, $needle)
{
     $length = strlen($needle);
     return (substr($haystack, 0, $length) === $needle);
}

function endsWith($haystack, $needle)
{
    $length = strlen($needle);

    return $length === 0 || 
    (substr($haystack, -$length) === $needle);
}

Utilisez ceci si vous ne voulez pas utiliser une regex.


1291
2018-05-07 12:24



Il est possible d'utiliser strrpos et strpos pour vérifier start-with et se termine-avec respectivement.

Notez que l'utilisation strrpos vérifier commence avec et strpos pour vérifier se termine avec retournera dès que possible au lieu de vérifier toute la chaîne jusqu'à la fin. En outre, cette solution ne crée pas de chaîne temporaire. Envisager d'expliquer la raison avant de downvoting. Juste parce qu'un f-wit au DWTF ne comprend pas comment cette fonction fonctionne ou pense qu'il n'y a qu'une seule solution ne signifie pas que cette réponse est fausse.

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

Tests et résultats (comparer avec ça):

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

Noter la strncmp et substr_compare les fonctions surpasseront cette fonction.


936
2018-05-06 18:22



Dernière mise à jour: 23 août 2016

Les fonctions

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

Tests

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";
}

Résultats (PHP 7.0.9)

(Tri le plus rapide au plus lent)

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

Résultats (PHP 5.3.29)

(Tri le plus rapide au plus lent)

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

startswith_benchmark.php


217
2017-08-24 00:07



Toutes les réponses à ce jour semblent faire beaucoup de travail inutile, strlen calculations, string allocations (substr), etc. 'strpos' et 'stripos' fonctions retournent l'indice de la première occurrence de $needle dans $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;
}

127
2018-05-13 21:23



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édit à:

Vérifiez si une chaîne se termine par une autre chaîne

Vérifiez si une chaîne commence par une autre chaîne


45
2018-05-07 12:15



Les fonctions regex ci-dessus, mais avec les autres tweaks également suggérés ci-dessus:

 function startsWith($needle, $haystack) {
     return preg_match('/^' . preg_quote($needle, '/') . '/', $haystack);
 }

 function endsWith($needle, $haystack) {
     return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);
 }

24
2018-06-19 16:11



Si la vitesse est importante pour vous, essayez ceci (je crois que c'est la méthode la plus rapide)

Fonctionne uniquement pour les chaînes et si $ haystack est seulement 1 caractère

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

21
2017-12-15 08:53



Je réalise que cela a été terminé, mais vous pouvez regarder strncmp car il vous permet de mettre la longueur de la chaîne à comparer, donc:

function startsWith($haystack, $needle, $case=true) {
    if ($case)
        return strncasecmp($haystack, $needle, strlen($needle)) == 0;
    else
        return strncmp($haystack, $needle, strlen($needle)) == 0;
}    

15
2017-09-17 02:50



Voici deux fonctions qui n'introduisent pas de chaîne temporaire, ce qui peut être utile lorsque les aiguilles sont substantiellement 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;
}

15
2017-08-02 07:40



Cette question a déjà de nombreuses réponses, mais dans certains cas, vous pouvez vous contenter de quelque chose de plus simple que tous. Si la chaîne que vous recherchez est connue (codée en dur), vous pouvez utiliser des expressions régulières sans aucun guillemets, etc.

Vérifiez si une chaîne commence par 'ABC':

preg_match('/^ABC/', $myString); // "^" here means beginning of string

se termine par "ABC":

preg_match('/ABC$/', $myString); // "$" here means end of string

Dans mon cas simple, je voulais vérifier si une chaîne se termine par une barre oblique:

preg_match('/\/$/', $myPath);   // slash has to be quoted

L'avantage: puisque c'est très court et simple, vous n'avez pas besoin de définir une fonction (telle que endsWith()) Comme montré ci-dessus.

Mais encore une fois - ce n'est pas une solution pour chaque cas, juste celui-là très spécifique.


13
2018-01-06 08:59