1701 Stimmen

startsWith() und endsWith() Funktionen in PHP

Wie kann ich zwei Funktionen schreiben, die eine Zeichenkette nehmen und zurückgeben würden, wenn sie mit dem angegebenen Zeichen/der angegebenen Zeichenkette beginnt oder damit endet?

Zum Beispiel:

$str = '|apples}';

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

26 Stimmen

Siehe Laravels Klasse Str startsWith() und endsWith() für erprobt Methoden. Grenzfälle Die weite Verbreitung dieses Codes ist also ein Vorteil.

1 Stimmen

Sie finden vielleicht s($str)->startsWith('|') y s($str)->endsWith('}') hilfreich, wie sie in diese eigenständige Bibliothek .

5 Stimmen

Warnung: Die meisten Antworten hier sind unzuverlässig bei Multi-Byte-Kodierungen wie UTF-8.

1869voto

MrHus Punkte 31640

PHP 8.0 und höher

Seit PHP 8.0 können Sie die

str_starts_with Handbuch et

str_ends_with Handbuch

Beispiel

echo str_starts_with($str, '|');

PHP vor 8.0

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

function endsWith( $haystack, $needle ) {
    $length = strlen( $needle );
    if( !$length ) {
        return true;
    }
    return substr( $haystack, -$length ) === $needle;
}

0 Stimmen

Variablennamen sind unklar. z.B. ist char eine Zeichenkette, nicht ein einzelnes Zeichen. Vielleicht sollte man params in konventionelle php $haystack und $needle umbenennen.

5 Stimmen

Nur zu Ihrer Information: Der Parameter $length in endsWith() ist überflüssig, da substr() wird ohnehin am Ende der Zeichenkette enden.

20 Stimmen

Ich würde sagen, endsWith('foo', '') == false ist das richtige Verhalten. Denn foo endet nicht mit nichts. 'Foo' endet mit 'o', 'oo' und 'Foo'.

1106voto

Salman A Punkte 246207

Sie können verwenden substr_compare Funktion zur Überprüfung von start-with und ends-with:

function startsWith($haystack, $needle) {
    return substr_compare($haystack, $needle, 0, strlen($needle)) === 0;
}
function endsWith($haystack, $needle) {
    return substr_compare($haystack, $needle, -strlen($needle)) === 0;
}

Dies sollte eine der schnellsten Lösungen unter PHP 7 sein ( Benchmark-Skript ). Getestet gegen 8KB Heuhaufen, verschieden lange Nadeln und vollständige, teilweise und keine Übereinstimmung. strncmp ist ein wenig schneller für starts-with, aber es kann ends-with nicht überprüfen.

85 Stimmen

Diese Antwort hat es in die Daily WTF geschafft :D Siehe thedailywtf.com/articles/

0 Stimmen

Bitte beachten Sie, dass sich die Kommentare von @DavidWallace und @FrancescoMM auf eine ältere Version dieser Antwort beziehen. Die aktuelle Antwort verwendet strrpos die sofort fehlschlagen (sollten), wenn needle nicht mit dem Anfang von haystack übereinstimmt.

2 Stimmen

Das verstehe ich nicht. Basierend auf php.net/handbuch/de/funktion.strrpos.php : "Wenn der Wert negativ ist, beginnt die Suche stattdessen mit so vielen Zeichen vom Ende der Zeichenkette, wobei rückwärts gesucht wird." Dies scheint darauf hinzuweisen, dass wir bei Zeichen 0 beginnen (aufgrund von -strlength($haystack) ) und die Suche rückwärts von dort? Bedeutet das nicht, dass Sie gar nichts suchen? Ich verstehe auch nicht die !== false Teile hiervon. Ich vermute, dies ist auf eine Eigenart von PHP, wo einige Werte "truthy" und andere "falsy" sind, aber wie funktioniert das in diesem Fall?

261voto

mpen Punkte 253762

Aktualisiert 23-Aug-2016

Funktionen

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

Ergebnisse (PHP 7.0.9)

(Sortiert vom schnellsten zum langsamsten)

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

Ergebnisse (PHP 5.3.29)

(Sortiert vom schnellsten zum langsamsten)

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

startmit_benchmark.php

3 Stimmen

Wenn die Zeichenketten nicht leer sind, wie in Ihren Tests, ist dies tatsächlich etwas (20-30%) schneller: function startswith5b($haystack, $needle) {return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;} Ich habe unten eine Antwort hinzugefügt.

0 Stimmen

@FrancescoMM Ich habe Ihre Version in meine Tests aufgenommen. Das scheint nicht zu stimmen; zumindest nicht, wenn der erste Buchstabe eine Chance von 1 zu 64 hat, ein Treffer zu sein.

0 Stimmen

Seltsam, es kann von der PHP-Implementierung abhängen, da ich es mit dem gleichen Set getestet habe. Trotzdem danke für das Hinzufügen

147voto

Sander Rijken Punkte 21069

Alle bisherigen Antworten scheinen eine Menge unnötiger Arbeit zu verursachen, strlen calculations , string allocations (substr) , usw. Die 'strpos' y 'stripos' Funktionen geben den Index des ersten Vorkommens von $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;
}

2 Stimmen

endsWith() Funktion hat einen Fehler. Die erste Zeile sollte lauten (ohne -1): $expectedPosition = strlen($haystack) - strlen($needle);

7 Stimmen

Die Funktion strlen() ist nicht unnötig. Falls die Zeichenkette nicht mit der angegebenen Nadel beginnt, wird Ihr Code unnötigerweise den ganzen Heuhaufen durchsuchen.

0 Stimmen

Sie glauben, dass es billiger ist, die gesamte Zeichenkette zu scannen, als nur den Anfang zu prüfen? Ich glaube nicht, dass Strpos billiger ist.

54voto

KdgDev Punkte 13733
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);
}

Kredit an :

Prüfen, ob eine Zeichenkette mit einer anderen Zeichenkette endet

Prüfen, ob eine Zeichenkette mit einer anderen Zeichenkette beginnt

2 Stimmen

Strtolower ist nicht der beste Weg, um Funktionen ohne Berücksichtigung der Groß-/Kleinschreibung zu erstellen. In einigen Sprachräumen ist die Groß- und Kleinschreibung komplexer als nur Groß und Klein.

9 Stimmen

Ich sehe Klagen und keine Lösung... Wenn du schon sagst, dass es schlecht ist, dann solltest du auch ein Beispiel dafür geben, wie es sein sollte.

2 Stimmen

@WebDevHobo: Deshalb habe ich einen Tag vor deinem Kommentar selbst eine Antwort hinzugefügt. Für Ihren Code war strcasecmp tatsächlich das Richtige.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X