Bagaimana saya bisa menulis dua fungsi yang akan mengambil string dan kembali jika dimulai dengan yang ditentukan karakter/string atau berakhir dengan itu?
Misalnya:
$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);
}
Gunakan ini jika anda don't ingin menggunakan regex.
Anda dapat menggunakan substr_compare
fungsi untuk memeriksa start-dengan dan diakhiri dengan:
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;
}
Ini harus menjadi salah satu solusi tercepat pada PHP 7 (patokan script). Diuji terhadap 8KB tumpukan jerami, berbagai panjang jarum dan penuh, parsial dan tidak sesuai kasus. strncmp
adalah sentuhan yang lebih cepat untuk mulai dengan, tetapi itu tidak bisa memeriksa berakhir-dengan.
Diperbarui 23-Jan-2016
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";
}
(Diurutkan paling cepat ke yang paling lambat)
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
(Diurutkan paling cepat ke yang paling lambat)
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
Semua jawaban sejauh ini tampaknya melakukan banyak pekerjaan yang tidak perlu, strlen perhitungan
, string alokasi (substr)
, dll. The 'strpos'
dan 'stripos'
fungsi mengembalikan indeks dari kemunculan pertama $jarum
di $jerami
:
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);
}
Kredit:
Regex fungsi-fungsi di atas, tetapi dengan tweak lain juga disarankan di atas:
function startsWith($needle, $haystack) {
return preg_match('/^' . preg_quote($needle, '/') . '/', $haystack);
}
function endsWith($needle, $haystack) {
return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);
}
Pertanyaan ini sudah memiliki banyak jawaban, tetapi dalam beberapa kasus, anda dapat menetap untuk sesuatu yang lebih sederhana daripada semua dari mereka. Jika string anda'kembali mencari dikenal (hardcoded), anda dapat menggunakan ekspresi reguler tanpa mengutip dll.
Memeriksa apakah string dimulai dengan 'ABC':
preg_match('/^ABC/', $myString); // "^" here means beginning of string
berakhir dengan 'ABC':
preg_match('/ABC$/', $myString); // "$" here means end of string
Dalam kasus sederhana, saya ingin memeriksa apakah string yang diakhiri dengan slash:
preg_match('#/$#', $myPath); // Use "#" as delimiter instead of escaping slash
Keuntungan: karena itu's sangat pendek dan sederhana, anda don't harus mendefinisikan fungsi (seperti endsWith()
) seperti yang ditunjukkan di atas.
Tapi lagi-ini bukan solusi untuk setiap kasus, hanya ini yang sangat spesifik.
Jika kecepatan adalah penting bagi anda, cobalah ini.(Saya percaya itu adalah metode tercepat)
Bekerja hanya untuk string dan jika $jerami hanya 1 karakter
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
Berikut ini adalah dua fungsi yang don't memperkenalkan sementara string, yang dapat berguna ketika jarum secara substansial besar:
function startsWith($haystack, $needle)
{
return strncmp($haystack, $needle, strlen($needle)) === 0;
}
function endsWith($haystack, $needle)
{
return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0;
}
Saya menyadari ini telah selesai, tetapi anda mungkin ingin melihat strncmp hal ini memungkinkan anda untuk menempatkan panjang string untuk membandingkan melawan, sehingga:
function startsWith($haystack, $needle, $case=true) {
if ($case)
return strncasecmp($haystack, $needle, strlen($needle)) == 0;
else
return strncmp($haystack, $needle, strlen($needle)) == 0;
}
# 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
Anda dapat menggunakan strpos
dan strrpos
$bStartsWith = strpos($sHaystack, $sNeedle) == 0;
$bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);
Pendek dan mudah-untuk-memahami satu-liners tanpa ekspresi reguler.
startsWith() adalah lurus ke depan.
function startsWith($haystack, $needle) {
return (strpos($haystack, $needle) === 0);
}
endsWith() menggunakan sedikit mewah dan lambat strrev():
function endsWith($haystack, $needle) {
return (strpos(strrev($haystack), strrev($needle)) === 0);
}
Berikut ini's multi-byte versi aman dari jawaban yang diterima, itu bekerja dengan baik untuk UTF-8 string:
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);
}
Berfokus pada startswith, jika anda yakin string yang kosong, menambahkan tes pada char pertama, sebelum perbandingan, strlen, dll., kecepatan hal-hal sedikit:
function startswith5b($haystack, $needle) {
return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;
}
Hal ini entah bagaimana (20%-30%) lebih cepat. Menambah char tes, seperti $jerami{1}===$jarum{1} tampaknya tidak speedup hal-hal yang jauh, bahkan mungkin memperlambat.
===
tampaknya lebih cepat dari ==
Conditional operator (a)?b:c
tampaknya lebih cepat dari jika(a) b; else c;
Untuk meminta mereka "mengapa tidak menggunakan strpos?" memanggil solusi lain "pekerjaan yang tidak perlu"
strpos lebih cepat, tapi itu bukan alat yang tepat untuk pekerjaan ini.
Untuk memahami, berikut ini adalah sedikit simulasi sebagai contoh:
Search a12345678c inside bcdefga12345678xbbbbb.....bbbbba12345678c
Apa komputer tidak "dalam"?
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
Dengan asumsi strlen tidak iterate seluruh string (tetapi bahkan dalam kasus itu) ini adalah sama sekali tidak nyaman.
Saya berharap bahwa jawaban di bawah ini dapat menjadi efisien dan juga sederhana:
$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';
Jawaban oleh mpen adalah sangat menyeluruh, tapi, sayangnya, yang disediakan acuan yang sangat penting dan merugikan pengawasan.
Karena setiap byte dalam jarum dan jerami adalah benar-benar acak, probabilitas bahwa jarum-jerami pasangan akan berbeda pada byte pertama adalah 99.609375%, yang berarti bahwa rata-rata, tentang 99609 dari 100000 pasangan akan berbeda pada byte pertama. Dengan kata lain, indeks ini sangat bias terhadap startswith
implementasi yang memeriksa byte pertama secara eksplisit, sebagai strncmp_startswith2
tidak.
Jika tes menghasilkan loop ini bukan dilaksanakan sebagai berikut:
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 />";
hasil benchmark memberitahu cerita yang sedikit berbeda:
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
Tentu saja, penghitungan ini mungkin masih tidak sempurna dan tidak bias, tetapi tes efisiensi algoritma ketika mengingat sebagian pencocokan jarum juga.
Biasanya saya akhirnya pergi dengan perpustakaan seperti underscore-php hari ini.
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
Perpustakaan ini penuh dengan lainnya fungsi praktis.
Hal ini dapat bekerja
function startsWith($haystack, $needle) {
return substr($haystack, 0, strlen($needle)) == $needle;
}
The substr
fungsi dapat kembali palsu
di banyak kasus-kasus khusus, jadi di sini adalah versi saya, yang berkaitan dengan masalah ini:
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
}
Tes (benar
berarti baik):
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'));
Juga, substr_compare
fungsi juga layak melihat.
http://www.php.net/manual/en/function.substr-compare.php