문제

지정된 문자/문자열로 시작하거나 끝나면 문자열을 취하고 리턴하는 두 가지 함수를 어떻게 작성할 수 있습니까?

예를 들어:

$str = '|apples}';

echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
도움이 되었습니까?

해결책

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

Regex를 사용하지 않으려면 사용하십시오.

다른 팁

당신이 사용할 수있는 substr_compare 시작 및 끝을 확인하는 기능 :

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

이것은 PHP 7에서 가장 빠른 솔루션 중 하나 여야합니다 (벤치 마크 스크립트). 8KB 건초 더미, 다양한 길이 바늘 및 전체, 부분 및 일치 사례에 대해 테스트했습니다. strncmp 시작에 대한 터치가 더 빠르지 만 끝을 확인할 수는 없습니다.

2016 년 23 월 23 일 업데이트

기능

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

테스트

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

결과 (PHP 7.0.9)

(가장 느리게 정렬)

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

결과 (php 5.3.29)

(가장 느리게 정렬)

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

지금까지 모든 답변은 많은 불필요한 작업을 수행하는 것 같습니다. strlen calculations, string allocations (substr), 등 'strpos' 그리고 'stripos' 함수는 첫 번째 발생의 색인을 반환합니다 $needle 안에 $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;
}
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);
}

신용:

문자열이 다른 문자열로 끝 있는지 확인하십시오

문자열이 다른 문자열로 시작하는지 확인하십시오

위의 Regex 기능이지만 다른 조정과 함께 위에서 제안한 것도 다음과 같습니다.

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

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

이 질문에는 이미 많은 답변이 있지만 경우에 따라 모든 대답이있는 것보다 더 간단한 것을 해결할 수 있습니다. 찾고있는 문자열이 알려진 경우 (하드 코드) 인용 등의 정규식을 사용할 수 있습니다.

문자열이 'ABC'로 시작하는지 확인하십시오.

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

'ABC'로 끝납니다.

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

간단한 경우, 문자열이 슬래시로 끝나는지 확인하고 싶었습니다.

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

장점 : 매우 짧고 간단하기 때문에 함수를 정의 할 필요가 없습니다 (예 : endsWith()위에서 볼 수 있듯이.

그러나 다시 - 이것은 모든 경우에 대한 해결책이 아니라 매우 구체적인 솔루션입니다.

속도가 중요하다면, 이것을 시도하십시오. (나는 그것이 가장 빠른 방법이라고 생각합니다)

문자열에 대해서만 작동하고 $ haystack이 단지 1 문자 인 경우

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

다음은 임시 문자열을 소개하지 않는 두 가지 기능입니다. 바늘이 실질적으로 큰 경우 유용 할 수 있습니다.

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

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

나는 이것이 끝났다는 것을 알고 있지만, 당신은보고 싶을 수도 있습니다 strncmp 그것은 당신이 문자열의 길이를 비교할 수 있도록 할 수 있으므로 :

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

빠른 ENDSWITH () 솔루션 :

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

기준:

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

벤치 마크 결과 :

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

당신이 사용할 수있는 strpos 그리고 strrpos

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

정규 표현이없는 짧고 이해하기 쉬운 1 라이너.

startswith ()가 간단합니다.

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

endswith ()는 약간 화려하고 느린 strrev ()를 사용합니다.

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

다음은 허용 된 답변의 멀티 바이트 안전 버전입니다. UTF-8 문자열에는 적합합니다.

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

STARTSWITH에 중점을두면 문자열이 비어 있지 않다고 확신하면 첫 번째 문자에 테스트를 추가하고 비교하기 전에 Strlen 등을 약간 속도를 내립니다.

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

어떻게 든 더 빠릅니다 (20%-30%). $ haystack {1} === $ 니들 {1}과 같은 다른 Char 테스트를 추가하는 것은 속도가 빠르지 않은 것처럼 보이며 속도가 느려질 수 있습니다.

=== 보다 빠른 것 같습니다 ==조건부 운영자 (a)?b:c 보다 빠른 것 같습니다 if(a) b; else c;


"Strpos를 사용하지 않는 이유는 무엇입니까?"라고 묻는 사람들을 위해. 다른 솔루션을 "불필요한 작업"이라고 부릅니다.


STRPO는 빠르지만이 작업에 적합한 도구는 아닙니다.

이해하려면 여기에 작은 시뮬레이션이 있습니다.

Search a12345678c inside bcdefga12345678xbbbbb.....bbbbba12345678c

컴퓨터가 "내부"하는 일은 무엇입니까?

    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이 전체 문자열을 반복하지는 않지만 (이 경우에도) 이것은 전혀 편리하지 않습니다.

아래 답변이 효율적이고 간단하기를 바랍니다.

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

나는 보통 도서관과 같은 도서관을 사용하게됩니다 밑줄 -php 요즘에는.

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   

도서관은 다른 편리한 기능으로 가득합니다.

그만큼 대답 ~에 의해 MPEN 엄청나게 철저하지만 불행히도 제공된 벤치 마크는 매우 중요하고 해로운 감독을 가지고 있습니다.

바늘과 건초 더미의 모든 바이트는 완전히 무작위이므로 바늘 스택 쌍이 첫 바이트에서 다를 확률은 99.609375%입니다. . 다시 말해, 벤치 마크는 크게 편향되어 있습니다. startswith 첫 바이트를 명시 적으로 확인하는 구현 strncmp_startswith2 하다.

테스트 생성 루프가 다음과 같이 구현되는 경우.

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

벤치 마크 결과는 약간 다른 이야기를합니다.

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

물론,이 벤치 마크는 여전히 완벽하게 편향되지 않을 수 있지만 부분적으로 일치하는 바늘이 주어지면 알고리즘의 효율성을 테스트합니다.

그만큼 substr 기능이 반환 될 수 있습니다 false 많은 특별한 경우에는 다음과 같은 내 버전이 있습니다.

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
}

테스트 (true 좋은 의미) :

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

또한, substr_compare 기능도 볼 가치가 있습니다.http://www.php.net/manual/en/function.substr-compare.php

요컨대 :

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

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

이것은 효과가있을 수 있습니다

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

원천: https://stackoverflow.com/a/4419658

왜 다음은하지 않습니까?

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

산출:

ValueHaystack의 시작 부분에서 가치를 찾았습니다!

명심하고, strpos 바늘이 건초 더미에서 발견되지 않은 경우 거짓을 반환하고 색인 0 (일명 시작)에서 바늘이 발견 된 경우에만 0을 반환합니다.

그리고 여기에 끝이 있습니다.

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

이 시나리오에서는 다음과 같은 함수 startswith ()가 필요하지 않습니다.

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

진실 또는 거짓을 정확하게 반환합니다.

여기서 만연한 모든 야생 기능이있는 것은 이상한 것 같습니다.

나는 이렇게 할 것이다

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

권장 사항 :

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

문자열의 첫 번째 캐릭터를 비교하는 추가 선은 잘못된 케이스를 반환 할 수 있습니다. 즉시, 따라서 많은 비교를 훨씬 빨리 만들었습니다 (측정 할 때 더 빨리 7 배 더 빠릅니다). 진정한 경우 당신은 그 단일 라인의 성능에 대해 사실상 가격을 지불하지 않으므로 그만한 가치가 있다고 생각합니다. (실제로, 특정 시작 청크에 대해 많은 문자열을 테스트 할 때, 대부분의 비교는 일반적인 경우 무언가를 찾고 있기 때문에 실패합니다.)

정규식을 사용할 수도 있습니다.

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

이전 답변 중 많은 부분도 잘 작동합니다. 그러나 이것은 아마도 당신이 그것을 만들고 원하는 것을 할 수있는 한 짧을 것입니다. 당신은 단지 당신이 '진실을 반환하기를 원한다고 말합니다. 그래서 나는 부울 진실/거짓과 텍스트 참/거짓을 반환하는 솔루션을 포함시켰다.

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

James Black의 답변을 기반으로, 여기에 Endswith 버전이 있습니다.

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

}

참고 : StrncaseCMP는 실제로 strncmp의 사례에 민감하지 않은 버전이기 때문에 James Black의 Startswith 기능에 대한 if-else 부분을 교체했습니다.

PHP 4에 대한 효율적인 솔루션은 다음과 같습니다. PHP 5에서 사용하면 더 빠른 결과를 얻을 수 있습니다. substr_compare 대신에 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

이것이 사람들에게 왜 그렇게 어려운지 잘 모르겠습니다. Substr은 훌륭한 작업을 수행하며 일치하지 않으면 전체 문자열을 검색 할 필요가 없으므로 효율적입니다.

또한 정수 값을 확인하지 않고 문자열을 비교하기 때문에 엄격한 === 케이스에 대해 걱정할 필요는 없습니다. 그러나 ===는 들어가기에 좋은 습관입니다.

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

또는 더 잘 최적화되었습니다.

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

function endsWith($haystack,$needle) {
  return substring($haystack,-strlen($needle)) == $needle);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top