문자열을 받아서 지정된 문자/문자열로 시작하거나 끝나는 경우 반환하는 두 가지 함수를 작성하려면 어떻게 해야 합니까?
예를 들어:
$str = '|apples}'; echo startsWith($str, '|'); //Returns true echo endsWith($str, '}'); //Returns true
질문자 :Ali
문자열을 받아서 지정된 문자/문자열로 시작하거나 끝나는 경우 반환하는 두 가지 함수를 작성하려면 어떻게 해야 합니까?
예를 들어:
$str = '|apples}'; echo startsWith($str, '|'); //Returns true echo endsWith($str, '}'); //Returns true
PHP 8.0부터 str_starts_with
및 str_ends_with
함수를 사용할 수 있습니다.
echo str_starts_with($str, '|');
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; }
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년 8월 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"; }
(가장 빠른 순으로 정렬)
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
(가장 빠른 순으로 정렬)
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
지금까지의 모든 답변은 불필요한 작업, strlen calculations
, string allocations (substr)
등 'strpos'
및 'stripos'
함수는 $haystack
$needle
이 처음 발생한 인덱스를 반환합니다.
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; }
PHP 8에는 마침내 이 문제에 대한 성능과 편리한 솔루션을 제공하는 str_starts_with
및 str_ends_with
$str = "beginningMiddleEnd"; if (str_starts_with($str, "beg")) echo "printed\n"; if (str_starts_with($str, "Beg")) echo "not printed\n"; if (str_ends_with($str, "End")) echo "printed\n"; if (str_ends_with($str, "end")) echo "not printed\n";
이 기능에 대한 RFC는 더 많은 정보와 명백한(그리고 그렇게 분명하지 않은) 사용자 영역 구현의 장점과 문제에 대한 논의도 제공합니다.
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); }
크레딧 :
이 질문에는 이미 많은 답변이 있지만 경우에 따라 모든 답변보다 간단한 것으로 해결할 수 있습니다. 찾고 있는 문자열이 알려진 경우(하드코딩된) 따옴표 등을 사용하지 않고 정규식을 사용할 수 있습니다.
문자열이 '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()
하지만 다시 -- 이것은 모든 경우에 대한 해결책이 아니라 매우 특정한 경우일 뿐입니다.
정규식은 위의 기능이지만 위에서 제안한 다른 조정도 있습니다.
function startsWith($needle, $haystack) { return preg_match('/^' . preg_quote($needle, '/') . '/', $haystack); } function endsWith($needle, $haystack) { return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack); }
속도가 중요하다면 이것을 시도하십시오.(가장 빠른 방법이라고 생각합니다)
문자열에 대해서만 작동하며 $haystack이 1자일 경우에만 작동합니다.
function startsWithChar($needle, $haystack) { return ($needle === $haystack[0]); } function endsWithChar($needle, $haystack) { return ($needle === $haystack[strlen($haystack) - 1]); } $str='|apples}'; echo startsWithChar('|',$str); //Returns true echo endsWithChar('}',$str); //Returns true echo startsWithChar('=',$str); //Returns false echo endsWithChar('#',$str); //Returns false
# 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
다음은 바늘이 상당히 클 때 유용할 수 있는 임시 문자열을 도입하지 않는 두 가지 기능입니다.
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; }
다음은 허용되는 답변의 멀티 바이트 안전 버전입니다. 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); }
$bStartsWith = strpos($sHaystack, $sNeedle) == 0; $bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);
정규 표현식이 없는 짧고 이해하기 쉬운 한 줄.
startsWith()는 간단합니다.
function startsWith($haystack, $needle) { return (strpos($haystack, $needle) === 0); }
endWith()는 약간 화려하고 느린 strrev()를 사용합니다.
function endsWith($haystack, $needle) { return (strpos(strrev($haystack), strrev($needle)) === 0); }
문자열이 비어 있지 않다고 확신하는 경우 비교 전에 strlen 등의 첫 번째 문자에 대한 테스트를 추가하면 작업 속도가 약간 빨라집니다.
function startswith5b($haystack, $needle) { return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE; }
어떻게 든 (20 %-30 %) 더 빠릅니다. $haystack{1}===$needle{1}와 같은 다른 문자 테스트를 추가해도 속도가 크게 향상되지 않고 느려질 수도 있습니다.
===
==
보다 빠른 것 같습니다. 조건부 연산자 (a)?b:c
if(a) b; else c;
보다 빠른 것 같습니다. b; if(a) b; else c;
"왜 strpos를 사용하지 않습니까?"라고 묻는 사람들을 위해 다른 솔루션을 "불필요한 작업"이라고 부릅니다.
strpos는 빠르지만 이 작업에 적합한 도구는 아닙니다.
이해를 돕기 위해 다음과 같은 약간의 시뮬레이션이 있습니다.
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이 전체 문자열을 반복하지 않는다고 가정하면(그런 경우에도) 이것은 전혀 편리하지 않습니다.
PHP 8.0 str_starts_with
및 str_ends_with
두 가지 새로운 메소드가 구현되었습니다. 그러나 대소문자를 구분합니다. 함수는 true 또는 false를 반환합니다.
$str = 'apples'; var_dump(str_starts_with($str, 'a')); // bool(true) var_dump(str_starts_with($str, 'A')); // bool(false) var_dump(str_ends_with($str, 's')); // bool(true) var_dump(str_ends_with($str, 'S')); // bool(false)
@mpen 답변에서 가장 빠른 startsWith
기능: https://stackoverflow.com/a/7168986/7082164
가장 빠른 endsWith
@Lucas_Bustamante 응답 함수 : https://stackoverflow.com/a/51491517/7082164
아래 답변이 효율적이고 간단하기를 바랍니다.
$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';
나는 보통 요즘 underscore-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%입니다. 이는 평균적으로 100000 쌍 중 약 99609 쌍이 맨 처음 바이트에서 다를 것임을 의미합니다 . 즉, 벤치마크는 strncmp_startswith2
가 하는 것처럼 첫 번째 바이트를 명시적으로 확인하는 startswith
테스트 생성 루프가 다음과 같이 대신 구현되는 경우:
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
물론 이 벤치마크는 여전히 완벽하게 편향되지 않을 수 있지만 부분적으로 일치하는 바늘도 제공될 때 알고리즘의 효율성을 테스트합니다.
요컨대:
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) { if($needle==="") return true; if($haystack[0]<>$needle[0]) return false; // ------------------------- speed boost! return (0===substr_compare($haystack,$needle,0,strlen($needle))); }
문자열의 첫 번째 문자를 비교하는 추가 행은 false 대소문자를 즉시 반환하도록 할 수 있으므로 많은 비교를 훨씬 빠르게 수행할 수 있습니다(측정할 때 7배 더 빠름). 실제 경우에는 해당 단일 라인에 대해 성능 면에서 거의 비용을 지불하지 않으므로 포함할 가치가 있다고 생각합니다. (또한 실제로, 특정 시작 청크에 대해 많은 문자열을 테스트할 때 일반적인 경우에 무언가를 찾고 있기 때문에 대부분의 비교는 실패합니다.)
참고: 아래 @Tino의 의견에 있는 버그가 이미 수정되었습니다.
문자열 비교를 강제 실행하려면(즉, startsWith("1234",12)가 true일 것으로 예상함) 일부 유형 변환이 필요합니다.
function startsWith($haystack,$needle) { if($needle==="") return true; $haystack = (string)$haystack; $needle = (string)$needle; if($haystack[0]<>$needle[0]) return false; // ------------------------- speed boost! return (0===substr_compare($haystack,$needle,0,strlen($needle))); }
나는 그것이 필요하다고 생각하지 않지만 "boolean true가 at으로 시작합니까?"와 같은 질문으로 이어지는 흥미로운 극단적인 경우입니다. - 그래서 당신은 결정하지만 영원히 결정하십시오.
이것은 작동 할 수 있습니다
function startsWith($haystack, $needle) { return substr($haystack, 0, strlen($needle)) == $needle; }
8.0
PHP 8.0
은 str_starts_with
및 str_ends_with
도입했습니다.
str_starts_with( string $haystack , string $needle ) : bool
str_ends_with( string $haystack , string $needle ) : bool
귀하의 예를 들면 다음과 같습니다.
$str = '|apples}'; echo str_starts_with( $str, '|' ); //... true || 1 echo str_ends_with( $str, '}' ); //... true || 1
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
다음은 왜 안되나요?
//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
는 false를 반환하고 바늘이 인덱스 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)
true 또는 false를 정확하게 반환합니다.
여기에서 모든 야생 기능이 만연하는 것이 이렇게 간단하다는 것이 이상해 보입니다.
나는 이렇게 할 것이다
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; }
James Black의 답변에 따르면 다음은 끝입니다.
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 부분을 교체했습니다.
이전 답변 중 많은 부분도 마찬가지로 작동합니다. 그러나 이것은 가능한 한 짧고 원하는 대로 수행할 수 있습니다. 'true를 반환'하기를 원한다고 명시하면 됩니다. 그래서 부울 true/false 및 텍스트 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'; }
복사 금지 및 인턴 루프 금지:
function startsWith(string $string, string $start): bool { return strrpos($string, $start, - strlen($string)) !== false; } function endsWith(string $string, string $end): bool { return ($offset = strlen($string) - strlen($end)) >= 0 && strpos($string, $end, $offset) !== false; }
출처 : http:www.stackoverflow.com/questions/834303/startswith-and-endswith-functions-in-php
"메인 클래스를 찾거나 로드할 수 없음"은 무엇을 의미합니까? (0) | 2022.01.22 |
---|---|
JavaScript 객체에 키/값 쌍을 추가하려면 어떻게 해야 합니까? (0) | 2022.01.22 |
macOS 또는 OS X에 pip를 어떻게 설치합니까? (0) | 2022.01.22 |
Node.js 애플리케이션을 어떻게 디버깅합니까? (0) | 2022.01.22 |
SQL SELECT에서 IF...THEN을 어떻게 수행합니까? (0) | 2022.01.22 |