Frage

Wie kann ich schreibe zwei Funktionen, die eine Zeichenfolge nehmen und zurück, wenn es mit dem angegebenen Zeichen / Zeichenfolge beginnt oder endet mit ihm?

Zum Beispiel:

$str = '|apples}';

echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
War es hilfreich?

Lösung

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

Verwenden Sie diese Funktion, wenn Sie einen regulären Ausdruck nicht verwenden möchten.

Andere Tipps

Sie können mit substr_compare Funktion überprüfen Start mit und endet mit-:

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 auf PHP sein 7 ( Benchmark-Skript ) . Getestet gegen 8KB Heuhaufen, verschiedene Länge Nadeln und Voll-, Teil- und keine Übereinstimmung Fälle. strncmp ist ein Hauch schneller für starts-with aber es kann nicht überprüfen Enden-mit.

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)

(Sorted 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)

(Sorted 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

startswith_benchmark.php

Alle Antworten scheinen bisher viele unnötige Arbeit zu tun, strlen calculations, string allocations (substr) usw. Die 'strpos' und 'stripos' Funktionen den Index des ersten Auftretens von $needle in $haystack zurück:

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

Überprüfen Sie, ob ein String mit einem anderen Enden String

Überprüfen Sie, ob ein String mit einem anderen beginnt String

Die Regex Funktionen oben, aber mit dem anderen zwickt auch oben vorgeschlagen:

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

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

Diese Frage hat schon viele Antworten, aber in einigen Fällen können Sie für etwas einfacher als alle von ihnen absetzen. Wenn die Zeichenfolge, die Sie suchen, ist bekannt (fest einprogrammiert), können Sie reguläre Ausdrücke ohne Angabe usw. verwendet werden.

Überprüfen Sie, ob ein String beginnt mit 'ABC':

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

endet mit 'ABC':

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

In meinem einfachen Fall wollte ich überprüfen, ob eine Zeichenfolge mit Schrägstrich endet:

preg_match('#/$#', $myPath);   // Use "#" as delimiter instead of escaping slash

Der Vorteil: Da es sehr kurz ist und einfach, Sie müssen nicht eine Funktion (wie endsWith()) definieren, wie oben gezeigt

.

Aber auch hier -. Dies ist keine Lösung für jeden Fall, gerade diese sehr spezifischen

Wenn die Geschwindigkeit ist wichtig für Sie, versuchen Sie dies. (Ich glaube, es ist die schnellste Methode ist)

Funktioniert nur für Streicher und wenn $ Heuhaufen ist nur 1 Zeichen

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

Hier sind zwei Funktionen, die eine temporäre Zeichenfolge nicht vorstellen können, was nützlich sein könnte, wenn Nadeln im Wesentlichen groß sind:

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

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

Ich weiß, das fertig ist, aber Sie können unter strncmp da es Ihnen erlaubt, die Länge der Zeichenfolge zu setzen gegen zu vergleichen, so:

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

Schnellster endsWith () Lösung:

# Checks if a string ends in a string
function endsWith($haystack, $needle) {
    return substr($haystack,-strlen($needle))===$needle;
}

Benchmark:

# 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();

Ergebnisse:

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

Sie können mit strpos und strrpos

$bStartsWith = strpos($sHaystack, $sNeedle) == 0;
$bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);

Kurz und einfach zu verstehen Einzeiler ohne reguläre Ausdrücke.

starts () ist gerade nach vorne.

function startsWith($haystack, $needle) {
   return (strpos($haystack, $needle) === 0);
}

endsWith () verwendet die etwas Phantasie und langsam strrev ():

function endsWith($haystack, $needle) {
   return (strpos(strrev($haystack), strrev($needle)) === 0);
}

Hier ist eine multibytesicher Version der akzeptierten Antwort, es funktioniert gut für UTF-8-Zeichenfolge:

function startsWith($haystack, $needle)
{
    $length = mb_strlen($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);
}

Die Konzentration auf starts, wenn Sie sicher sind Strings nicht leer ist, einen Test auf dem ersten Zeichen hinzufügen, vor dem Vergleich, die Strlen usw., beschleunigt alles, ein bisschen:

function startswith5b($haystack, $needle) {
    return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;
}

Es ist irgendwie (20% -30%) schneller. Hinzufügen eines weiteren char-Test, wie $ Heuhaufen {1} === $ needle {1} scheint nicht Dinge Speedup viel, vielleicht sogar. Verlangsamen

=== scheint schneller als == Konditionaloperator (a)?b:c scheint schneller als if(a) b; else c;


Für diejenigen fragen, "warum nicht strpos benutzen?" Aufruf zu anderen Lösungen "unnötige Arbeit"


strpos ist schnell, aber es ist nicht das richtige Werkzeug für diesen Job.

Um zu verstehen, hier ist ein wenig Simulation als Beispiel:

Search a12345678c inside bcdefga12345678xbbbbb.....bbbbba12345678c

Was ist der Computer "innen"?

    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

strlen Unter der Annahme, nicht die gesamte Zeichenfolge laufen (aber auch in diesem Fall) das überhaupt nicht bequem ist.

Ich hoffe, dass die folgende Antwort effizient sein kann und auch einfach:

$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';

ich am Ende in der Regel mit einer Bibliothek gehen wie unterstreichen-php diese Tage.

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   

Die Bibliothek ist voll von anderen praktischen Funktionen.

Die beantworten von MPde ist unglaublich gründlich, aber leider die bereitgestellte Benchmark eine sehr wichtige und schädlich Aufsicht hat.

Da jedes Byte in Nadeln und Heu vollständig zufällig ist, dass die Wahrscheinlichkeit, ein nadel Heuhaufen Paar am ersten Byte unterscheiden ist 99.609375%, was bedeutet, dass im Durchschnitt etwa 99.609 der 100.000-Paare auf dem unterscheiden erster Byte. Mit anderen Worten, ist der Maßstab stark voreingenommen gegenüber startswith Implementierungen, die das erste Byte explizit prüfen, wie strncmp_startswith2 der Fall ist.

Wenn die Test-Erzeugungsschleife statt implementiert ist wie folgt:

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

Die Benchmark-Ergebnisse erzählen eine etwas andere Geschichte:

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

Natürlich kann dieser Benchmark noch nicht perfekt unvoreingenommen sein, aber es testet die Leistungsfähigkeit der Algorithmen, wenn auch teilweise passende Nadeln gegeben.

Die substr Funktion kann false in vielen Sonderfällen zurückkehren, also hier ist meine Version, die sich mit diesen Fragen beschäftigt:

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
}

Tests (true bedeutet gut):

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'));

Auch auch die substr_compare Funktion einen Blick wert. http://www.php.net/manual/en/function. substr-compare.php

kurzum:

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

function endsWith($str, $needle){
   $length = strlen($needle);
   return !$length || substr($str, - $length) === $needle;
}

Das kann funktionieren

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

Quelle: https://stackoverflow.com/a/4419658

Warum nicht die folgend?

//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 . "!";
}

Ausgabe:

  

Gefunden Wert am Anfang valuehaystack!

Beachten Sie, wird strpos falsch zurück, wenn die Nadel nicht im Heuhaufen gefunden wurde, und 0 zurück, wenn und nur wenn, wurde Nadel bei Index 0 (AKA des Anfang).

gefunden

Und hier ist endsWith:

$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 . "!";
}

In diesem Szenario gibt es keine Notwendigkeit für eine Funktion starts () als

(strpos($stringToSearch, $doesItStartWithThis) === 0)

wird wieder wahr oder falsch genau.

Es scheint seltsam, es so einfach ist mit all den wilden Funktionen grassierenden hier ausgeführt wird.

Ich würde es so tun

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

Nur eine Empfehlung:

function startsWith($haystack,$needle) {
    if($needle==="") return true;
    if($haystack[0]<>$needle[0]) return false; // ------------------------- speed boost!
    return (0===substr_compare($haystack,$needle,0,strlen($needle)));
}

, die zusätzliche Linie, das erste Zeichen des Strings zu vergleichen, kann das machen Falsch Fall Rückkehr sofort , daher viele Ihrer Vergleiche viel schneller (7x schneller als ich gemessen). Im wahren Fall zahlen Sie praktisch keinen Preis in der Leistung für die einzelne Zeile also denke ich, einschließlich es wert ist. (Auch in der Praxis, wenn Sie viele Strings für einen bestimmten Start chunk testen, werden die meisten Vergleiche scheitern, da in einem typischen Fall Sie nach etwas suchen.)

Sie können auch reguläre Ausdrücke verwenden:

function endsWith($haystack, $needle, $case=true) {
  return preg_match("/.*{$needle}$/" . (($case) ? "" : "i"), $haystack);
}

Viele der vorherigen Antworten werden genauso gut funktionieren. Dies ist jedoch möglicherweise so kurz wie Sie es machen können und es tun, was Sie sich wünschen. Sie sagen nur, dass Sie es möchten ‚return true‘. Also habe ich Lösungen enthalten, die boolean wahr / falsch und die textlichen wahr / falsch zurück.

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

Auf der Grundlage von James Black Antwort, hier ist seine endsWith Version:

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

}

. Hinweis: Ich habe den if-else-Teil für James Blacks starts Funktion getauscht, weil strncasecmp tatsächlich die Groß- und Kleinschreibung Version von strncmp ist

Hier ist eine effiziente Lösung für PHP 4. Sie schnellere Ergebnisse 5, wenn auf PHP bekommen könnten durch die Verwendung substr_compare statt 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;
}
$ends_with = strrchr($text, '.'); // Ends with dot
$start_with = (0 === strpos($text, '.')); // Starts with dot

Nicht sicher, warum dies so schwierig für die Menschen ist. Substr macht einen guten Job und ist effizient, wie Sie die gesamte Zeichenfolge nicht suchen müssen, wenn sie nicht übereinstimmen.

Darüber hinaus, da ich nicht ganzzahlige Werte überprüft, aber vergleichen Strings Ich muß nicht unbedingt über den strengen === Fall kümmern. Allerdings === ist eine gute Gewohnheit, in zu erhalten.

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

oder noch besser optimiert werden.

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

function endsWith($haystack,$needle) {
  return substring($haystack,-strlen($needle)) == $needle);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top