我如何编写两个带字符串的函数,如果它以指定的字符/字符串开头或以它结尾,则返回?
例如:
$str = '|apples}';
echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
Run Code Online (Sandbox Code Playgroud)
MrH*_*Hus 1520
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);
}
Run Code Online (Sandbox Code Playgroud)
如果您不想使用正则表达式,请使用此选项.
Sal*_*n A 989
可以分别使用substr_compare
和strncmp
检查start-with和end-with.
请注意,使用substr_compare
检查开始和strncmp
检查结束将尽快返回,而不是检查整个字符串直到结束.此外,此解决方案不会创建临时字符串.考虑在downvoting之前解释原因.仅仅因为DWTF的f-wit不理解这个功能如何工作或认为只有一个解决方案并不意味着这个答案是错误的.
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;
}
Run Code Online (Sandbox Code Playgroud)
测试和结果(与此相比):
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;
}
Run Code Online (Sandbox Code Playgroud)
注意:substr_compare
和strncmp
函数将胜过此函数.
mpe*_*pen 236
更新于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;
}
Run Code Online (Sandbox Code Playgroud)
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";
}
Run Code Online (Sandbox Code Playgroud)
(分类最快到最慢)
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
Run Code Online (Sandbox Code Playgroud)
(分类最快到最慢)
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
Run Code Online (Sandbox Code Playgroud)
San*_*ken 136
所有的答案到目前为止似乎做不必要的工作负载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;
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*Jon 49
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";
Run Code Online (Sandbox Code Playgroud)
此功能的RFC提供了更多信息,并且还讨论了明显(和不那么明显)的用户空间实现的优点和问题。
Kdg*_*Dev 46
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);
}
Run Code Online (Sandbox Code Playgroud)
信用到:
tri*_*ian 28
上面的正则表达式功能,但上面提到的其他调整:
function startsWith($needle, $haystack) {
return preg_match('/^' . preg_quote($needle, '/') . '/', $haystack);
}
function endsWith($needle, $haystack) {
return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);
}
Run Code Online (Sandbox Code Playgroud)
noa*_*mtm 25
这个问题已经有很多答案,但在某些情况下,你可以选择比所有这些更简单的东西.如果您要查找的字符串是已知的(硬编码),则可以使用正则表达式而无需任何引号等.
检查字符串是否以'ABC'开头:
preg_match('/^ABC/', $myString); // "^" here means beginning of string
Run Code Online (Sandbox Code Playgroud)
以'ABC'结尾:
preg_match('/ABC$/', $myString); // "$" here means end of string
Run Code Online (Sandbox Code Playgroud)
在我的简单案例中,我想检查字符串是否以斜杠结尾:
preg_match('#/$#', $myPath); // Use "#" as delimiter instead of escaping slash
Run Code Online (Sandbox Code Playgroud)
优点:由于它非常简短,您不必定义endsWith()
如上所示的功能(如).
但同样 - 这不是每个案例的解决方案,只是这个非常具体的案例.
lep*_*epe 22
如果速度对你很重要,试试这个.(我相信这是最快的方法)
仅适用于字符串,如果$ 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
Run Code Online (Sandbox Code Playgroud)
Ja͢*_*͢ck 18
这里有两个不引入临时字符串的函数,当针大得多时,它可能很有用:
function startsWith($haystack, $needle)
{
return strncmp($haystack, $needle, strlen($needle)) === 0;
}
function endsWith($haystack, $needle)
{
return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0;
}
Run Code Online (Sandbox Code Playgroud)
Jam*_*ack 16
我意识到这已经完成了,但你可能想看一下strncmp因为它允许你把字符串的长度进行比较,所以:
function startsWith($haystack, $needle, $case=true) {
if ($case)
return strncasecmp($haystack, $needle, strlen($needle)) == 0;
else
return strncmp($haystack, $needle, strlen($needle)) == 0;
}
Run Code Online (Sandbox Code Playgroud)
Luc*_*nte 14
# Checks if a string ends in a string
function endsWith($haystack, $needle) {
return substr($haystack,-strlen($needle))===$needle;
}
Run Code Online (Sandbox Code Playgroud)
# 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();
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
Lex*_*Lex 11
$bStartsWith = strpos($sHaystack, $sNeedle) == 0;
$bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);
Run Code Online (Sandbox Code Playgroud)
下面是接受的答案的多字节安全的版本,它工作得很好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);
}
Run Code Online (Sandbox Code Playgroud)
小智 8
简短易懂的单行内容,没有正则表达式.
startsWith()是直截了当的.
function startsWith($haystack, $needle) {
return (strpos($haystack, $needle) === 0);
}
Run Code Online (Sandbox Code Playgroud)
endsWith()使用稍微花哨和缓慢的strrev():
function endsWith($haystack, $needle) {
return (strpos(strrev($haystack), strrev($needle)) === 0);
}
Run Code Online (Sandbox Code Playgroud)
从PHP 8.0 开始,实现了两个新方法:str_starts_with
和str_ends_with
. 但是它们区分大小写。函数返回真或假。
$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)
Run Code Online (Sandbox Code Playgroud)
startsWith
@mpen 中最快的函数答案:https ://stackoverflow.com/a/7168986/7082164
endsWith
@Lucas_Bustamante 中最快的函数答案:https ://stackoverflow.com/a/51491517/7082164
专注于startwith,如果你确定字符串不为空,在比较之前在第一个字符串上添加测试,strlen等等,会加快速度:
function startswith5b($haystack, $needle) {
return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;
}
Run Code Online (Sandbox Code Playgroud)
它以某种方式(20%-30%)更快.添加另一个char测试,比如$ haystack {1} === $ needle {1}似乎没有加速,甚至可能放慢速度.
===
似乎比==
条件运算符(a)?b:c
更快似乎更快if(a) b; else c;
对于那些问"为什么不使用strpos?"的人 称其他解决方案"不必要的工作
strpos很快,但它不适合这项工作.
要理解,这里有一个小模拟作为例子:
Search a12345678c inside bcdefga12345678xbbbbb.....bbbbba12345678c
Run Code Online (Sandbox Code Playgroud)
计算机"内部"做什么?
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
Run Code Online (Sandbox Code Playgroud)
假设strlen没有迭代整个字符串(但即使在这种情况下),这根本不方便.
简而言之:
function startsWith($str, $needle){
return substr($str, 0, strlen($needle)) === $needle;
}
function endsWith($str, $needle){
$length = strlen($needle);
return !$length || substr($str, - $length) === $needle;
}
Run Code Online (Sandbox Code Playgroud)
我希望以下答案可能有效且简单:
$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';
Run Code Online (Sandbox Code Playgroud)
这些天我通常最终会使用像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
Run Code Online (Sandbox Code Playgroud)
该库充满了其他方便的功能.
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)));
}
Run Code Online (Sandbox Code Playgroud)
额外的一行,比较字符串的第一个字符,可以使错误的情况立即返回,因此使您的许多比较更快(我测量时快 7 倍)。在真实情况下,您几乎不会为那条单线支付性能上的任何代价,所以我认为值得包括在内。(此外,在实践中,当您为特定的起始块测试多个字符串时,大多数比较都会失败,因为在典型情况下您正在寻找某些东西。)
注意:下面@Tino 评论中的错误已经修复
如果您想强制进行字符串比较(也就是说,您希望 startsWith("1234",12) 为真),您需要进行一些类型转换:
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)));
}
Run Code Online (Sandbox Code Playgroud)
我不认为这是必要的,但这是一个有趣的边缘情况,导致诸如“布尔真是否以 at 开头?”之类的问题。- 所以你决定,但要确保你决定好。
小智 6
将答案通过MPEN是非常彻底的,但不幸的是,所提供的基准具有非常重要的和有害的监督.
因为针和干草堆中的每个字节都是完全随机的,所以针 - 干草堆对在第一个字节上的差异的概率是99.609375%,这意味着,平均而言,100000对中的大约99609在第一个字节上会有所不同.换句话说,基准测试严重偏向于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 />";
Run Code Online (Sandbox Code Playgroud)
基准测试结果说明了一个略有不同的故事
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
Run Code Online (Sandbox Code Playgroud)
当然,这个基准可能仍然不是完全不偏不倚的,但是当给出部分匹配的针时,它还会测试算法的效率.
这可能有效
function startsWith($haystack, $needle) {
return substr($haystack, 0, strlen($needle)) == $needle;
}
Run Code Online (Sandbox Code Playgroud)
来源:https : //stackoverflow.com/a/4419658
8.0
PHP8.0
已经推出str_starts_with
和str_ends_with
。
str_starts_with( string $haystack , string $needle ) : bool
Run Code Online (Sandbox Code Playgroud)
str_ends_with( string $haystack , string $needle ) : bool
Run Code Online (Sandbox Code Playgroud)
用你的例子,我们将有:
$str = '|apples}';
echo str_starts_with( $str, '|' ); //... true || 1
echo str_ends_with( $str, '}' ); //... true || 1
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
805247 次 |
最近记录: |