我如何编写两个函数,如果它以指定的字符/字符串开头或以指定的字符串结尾,那么它们将接受字符串并返回?
例如:
$str = '|apples}';
echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
我如何编写两个函数,如果它以指定的字符/字符串开头或以指定的字符串结尾,那么它们将接受字符串并返回?
例如:
$str = '|apples}';
echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
当前回答
根据詹姆斯·布莱克的回答,以下是其结尾版本:
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);
}
注意:我已将if else部分替换为James Black的startsWith函数,因为strncasecmp实际上是strncmp的不区分大小写版本。
其他回答
做得更快:
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 case会立即返回,因此会进行许多比较速度快得多(测量时快7倍)。在真实的情况下,你几乎没有为这条线付出任何性能代价,所以我认为这是值得的。(此外,在实践中,当您为一个特定的起始块测试多个字符串时,大多数比较都会失败,因为在典型的情况下,您正在寻找一些东西。)
注意:@Tino下面评论中的bug已经修复
对于字符串与整数
如果要强制字符串比较(即,期望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)));
}
我不认为这是必要的,但这是一个有趣的边缘案例,导致了诸如“布尔值真以t开头吗?”这样的问题,所以你要做出决定,但要确保你的决定是好的。
拉里维尔9.0
如果你正在使用Laravel,那么你可以执行以下操作(如果你没有使用Laraver,那么你真的应该这样做)。
Str::of('a long string')->startsWith('a');
Str::of('a long string')->endsWith('string');
//true
//true
Fastest 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
PHP 8.0及更高版本
从PHP 8.0开始,您可以使用
str_starts_with手册和
str_ends_with手动
实例
echo str_starts_with($str,'|');
8.0之前的PHP
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;
}
前面的许多答案也同样有效。然而,这可能是尽可能短的,你可以让它做你想做的事情。你只需要声明你希望它“回归真实”。因此,我包含了返回布尔值真/假和文本真/假的解决方案。
// 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';
}