文字列を受け取り、指定された文字/文字列で始まるか、それで終わる場合に戻る2つの関数をどのように記述できますか?
例えば:
$str = '|apples}';
echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
文字列を受け取り、指定された文字/文字列で始まるか、それで終わる場合に戻る2つの関数をどのように記述できますか?
例えば:
$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);
}
正規表現を使用したくない場合に使用します。
$length
の最後の行では不要ですendsWith()
。
return substr($haystack, -strlen($needle))===$needle;
if
渡すことで、完全に回避でき$length
ます。これは、全体ではなく空の文字列を返すことでケースを処理します。substr
return (substr($haystack, -$length, $length);
$length == 0
$haystack
substr_compare
関数を使用して、start-withおよびend-withをチェックできます。
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(ベンチマークスクリプト)の最速のソリューションの1つです。8KBの干し草の山、さまざまな長さの針、完全一致、部分一致、一致なしのケースに対してテストされています。strncmp
starts-withの方が少し高速ですが、ends-withをチェックできません。
strrpos
、needleがhaystackの先頭に一致しない場合、すぐに失敗する(すべき)を使用しています。
-strlength($haystack)
)から開始し、そこから後方検索していることを示しているようです。それはあなたが何も検索していないという意味ではありませんか?!== false
この部分も分からない。これは、いくつかの値が「真実」で他の値が「偽」であるPHPの癖に依存していると思いますが、この場合、どのように機能しますか?
xxxyyy
needle = yyy
でstrrpos
、検索の使用は最初のから始まりx
ます。ここで、一致は成功せず(yの代わりにxが見つかりました)、もう戻ることはできません(文字列の先頭にあります)。検索はすぐに失敗します。上記の例で!== false
- strrpos
を使用すると、0またはfalseが返され、他の値は返されません。同様strpos
に、上記の例では$temp
(期待される位置)またはfalseを返すことができます。私は一緒に行った!== false
一貫性のためではなく、あなたが使用することができます=== 0
し、=== $temp
それぞれの機能インチ
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
function startswith5b($haystack, $needle) {return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;}
。以下に返信を追加しました。
すべての答えは、これまでの不必要な作業の負荷を行うように見える、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;
}
endsWith()
関数にエラーがあります。その最初の行は(-1なし)でなければなりません:$expectedPosition = strlen($haystack) - strlen($needle);
strpos($haystack, "$needle", 0)
あるかどう任意の(それはから来ていた場合、例えばチャンスがすでに文字列ではありませんjson_decode()
)。そうしないと、[odd]のデフォルトの動作strpos()
により予期しない結果が生じる可能性があります: " needleが文字列でない場合、整数に変換され、文字の序数値として適用されます。 "
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);
}
クレジット:
上記の正規表現は機能しますが、他の調整も上記で提案されています:
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()
上記のように関数(など)を定義する必要はありません。
しかし、これもまた、すべての場合の解決策ではなく、非常に具体的なものです。
@
スラッシュ(/
)をエスケープする必要がないように、正規表現をのような他の文字で囲むことができます。例3のphp.net/manual/en/function.preg-match.phpを参照してください。
速度が重要な場合は、これを試してください(これが最速の方法だと思います)。
文字列に対してのみ機能し、$ 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
endsWithChar('','x')
、しかし結果は正しいです
一時的な文字列を導入しない2つの関数を次に示します。これは、針がかなり大きい場合に役立ちます。
function startsWith($haystack, $needle)
{
return strncmp($haystack, $needle, strlen($needle)) === 0;
}
function endsWith($haystack, $needle)
{
return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0;
}
endsWidth
行う必要がありますreturn $needle==='' || substr_compare(
...それがために期待どおりに動作-strlen($needle)===0
、修正せずに、どの作るendsWith('a','')
リターンfalse
endsWith('', 'foo')
は警告をトリガーします:「substr_compare():開始位置は最初の文字列の長さを超えることはできません」。多分それはの別のバグかもしれませsubstr_compare()
んが、それを回避するには、次のような事前チェックが必要です|| (strlen($needle) <= strlen($haystack) && substr_compare(
... ...) === 0);
return $needle === '' || @substr_compare(
この警告を抑制するには、..を使用するだけです。
# 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
これは完了したと思いますが、比較する文字列の長さを入力できるので、strncmpを確認することをお勧めします。
function startsWith($haystack, $needle, $case=true) {
if ($case)
return strncasecmp($haystack, $needle, strlen($needle)) == 0;
else
return strncmp($haystack, $needle, strlen($needle)) == 0;
}
あなたが使用することができますstrpos
し、strrpos
$bStartsWith = strpos($sHaystack, $sNeedle) == 0;
$bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);
strpos($sHaystack, $sNeedle) == 0
このようにここでトリプルイコールを使用する必要がありますstrpos($sHaystack, $sNeedle) === 0
か?にfalse == 0
評価すると、バグが表示されtrue
ます。
受け入れられた回答のマルチバイトセーフバージョンを以下に示します。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
、それがあるべき$length = mb_strlen($needle, 'UTF-8');
正規表現のない短くてわかりやすいワンライナー。
startsWith()は簡単です。
function startsWith($haystack, $needle) {
return (strpos($haystack, $needle) === 0);
}
endWith()は、少し派手で遅いstrrev()を使用しています。
function endsWith($haystack, $needle) {
return (strpos(strrev($haystack), strrev($needle)) === 0);
}
文字列が空でないことが確実な場合は、startswithに焦点を合わせ、比較やstrlenなどの前に最初の文字にテストを追加すると、処理が少し速くなります。
function startswith5b($haystack, $needle) {
return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;
}
なんとか(20%〜30%)高速です。$ haystack {1} === $ needle {1}のような別のcharテストを追加しても、速度はそれほど向上しないようで、遅くなることさえあります。
===
より速いと思われる==
条件演算子は(a)?b:c
速くよりも思えます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が文字列全体を反復しないと仮定すると(その場合でも)、これはまったく便利ではありません。
以下の答えが効率的で簡単かもしれないことを願っています:
$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は、残念ながら、提供ベンチマークは非常に重要かつ有害な監督を持って、信じられないほど徹底しているが、。
needlesとhaystackのすべてのバイトは完全にランダムであるため、needle-haystackペアが最初のバイトで異なる確率は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 />";
ベンチマークの結果は、少し異なるストーリーを示しています。
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)));
}
文字列の最初の文字を比較するその余分な行により、誤った大文字と小文字がすぐに返される可能性があります。そのため、多くの比較がはるかに速くなります(私が測定した場合は7倍速く)。実際のケースでは、その1行のパフォーマンスに実質的に料金を払わないので、含める価値があると思います。(また、実際には、特定の開始チャンクについて多くの文字列をテストする場合、一般的なケースでは何かを探しているため、ほとんどの比較は失敗します。)
startsWith("123", "0")
与えtrue
この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($haystack, $needle) {
return substr($haystack, 0, strlen($needle)) == $needle;
}
私はこのようにします
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の回答に基づいて、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部分を交換しました。
strrev()
は創造的ですが、特に非常にコストがかかることに注意してください。
===
代わりに==
を使用してください。0
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(AKA初め)で発見された、とだけ、場合場合は0を返します。
そしてこれが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 . "!";
}
このシナリオでは、関数startsWith()は必要ありません。
(strpos($stringToSearch, $doesItStartWithThis) === 0)
trueまたはfalseを正確に返します。
ここでは、すべての野生の関数が蔓延しているので、これは単純です。
strpos()
一致する場合を除いて、使用は遅くなります。strncmp()
この場合ははるかに良いでしょう。
以前の回答の多くも同様に機能します。しかし、これはあなたがそれを作って、あなたが望むことをさせることができる限り短いかもしれません。あなたはそれが「真に戻る」ことを望んでいると述べるだけです。そのため、ブール値の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';
}
'true'
、'false'
文字列として返されますtrue
。どちらもブール値の意味です。それはunderhanded.xcott.comのようなものには良いパターンです;)
正規表現を使用することもできます。
function endsWith($haystack, $needle, $case=true) {
return preg_match("/.*{$needle}$/" . (($case) ? "" : "i"), $haystack);
}
preg_quote($needle, '/')
ます。
コピーなし、インターンループなし:
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;
}
PHP 4の効率的なソリューションを次に示します。のsubstr_compare
代わりにを使用することにより、PHP 5でより高速な結果を得ることができます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;
}
これにはfnmatch関数を使用できます。
// Starts with.
fnmatch('prefix*', $haystack);
// Ends with.
fnmatch('*suffix', $haystack);