Bagaimana saya bisa menulis dua fungsi yang akan mengambil string dan kembali jika dimulai dengan karakter / string yang ditentukan atau diakhiri dengan itu?
Sebagai contoh:
$str = '|apples}';
echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
s($str)->startsWith('|')
dans($str)->endsWith('}')
membantu, seperti yang ditemukan di perpustakaan mandiri ini .Jawaban:
Gunakan ini jika Anda tidak ingin menggunakan regex.
sumber
$length
tidak diperlukan di baris terakhirendsWith()
.return substr($haystack, -strlen($needle))===$needle;
if
sama sekali dengan melewati$length
sebagai parameter ketiga untuksubstr
:return (substr($haystack, -$length, $length);
. Ini menangani kasus$length == 0
dengan mengembalikan string kosong dan bukan keseluruhan$haystack
.Anda dapat menggunakan
substr_compare
fungsi untuk memeriksa mulai-dengan dan berakhir-dengan:Ini harus menjadi salah satu solusi tercepat di PHP 7 ( skrip benchmark ). Diuji terhadap tumpukan jerami 8KB, berbagai jarum panjang dan penuh, sebagian dan tidak ada kotak korek api.
strncmp
adalah sentuhan yang lebih cepat untuk memulai-dengan tetapi tidak dapat memeriksa ujung-dengan.sumber
strrpos
yang (harus) gagal segera jika jarum tidak cocok dengan awal tumpukan jerami.-strlength($haystack)
) dan mencari mundur dari sana? Bukankah itu berarti Anda tidak mencari apa-apa? Saya juga tidak mengerti!== false
bagian dari ini. Saya menduga ini bergantung pada kekhasan PHP di mana beberapa nilai "benar" dan yang lain "palsu" tetapi bagaimana cara kerjanya dalam kasus ini?xxxyyy
needle =yyy
dan menggunakanstrrpos
pencarian dimulai dari yang pertamax
. Sekarang kami tidak memiliki kecocokan yang berhasil di sini (ditemukan x bukan y) dan kami tidak dapat mundur lagi (kami berada di awal string) pencarian gagal dengan segera . Tentang menggunakan!== false
-strrpos
dalam contoh di atas akan mengembalikan 0 atau salah dan bukan nilai lainnya. Demikian juga,strpos
dalam contoh di atas dapat mengembalikan$temp
(posisi yang diharapkan) atau salah. Saya pergi dengan!== false
konsistensi tetapi Anda dapat menggunakan=== 0
dan=== $temp
dalam fungsi masing-masing.Diperbarui 23-Agu-2016
Fungsi
Tes
Hasil (PHP 7.0.9)
(Diurutkan paling cepat hingga paling lambat)
Hasil (PHP 5.3.29)
(Diurutkan paling cepat hingga paling lambat)
startswith_benchmark.php
sumber
function startswith5b($haystack, $needle) {return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;}
Saya menambahkan balasan di bawah ini.Semua jawaban sejauh tampaknya melakukan banyak pekerjaan yang tidak perlu,
strlen calculations
,string allocations (substr)
, dll'strpos'
dan'stripos'
fungsi mengembalikan indeks dari kejadian pertama$needle
di$haystack
:sumber
endsWith()
fungsi memiliki kesalahan. Baris pertamanya adalah (tanpa -1):$expectedPosition = strlen($haystack) - strlen($needle);
strpos($haystack, "$needle", 0)
jika ada setiap kesempatan itu belum string (misalnya, jika itu berasal darijson_decode()
). Jika tidak, perilaku default [aneh]strpos()
dapat menyebabkan hasil yang tidak terduga: " Jika jarum bukan string, itu dikonversi ke integer dan diterapkan sebagai nilai ordinal karakter. "Kredit untuk :
Periksa apakah string berakhir dengan string lain
Periksa apakah string dimulai dengan string lain
sumber
Fungsi regex di atas, tetapi dengan tweak lainnya juga disarankan di atas:
sumber
Pertanyaan ini sudah memiliki banyak jawaban, tetapi dalam beberapa kasus Anda dapat menerima sesuatu yang lebih sederhana daripada semuanya. Jika string yang Anda cari diketahui (hardcoded), Anda dapat menggunakan ekspresi reguler tanpa mengutip dll.
Periksa apakah string dimulai dengan 'ABC':
diakhiri dengan 'ABC':
Dalam kasus sederhana saya, saya ingin memeriksa apakah string diakhiri dengan garis miring:
Keuntungan: karena sangat pendek dan sederhana, Anda tidak perlu mendefinisikan fungsi (seperti
endsWith()
) seperti yang ditunjukkan di atas.Tetapi sekali lagi - ini bukan solusi untuk setiap kasus, hanya ini yang sangat spesifik.
sumber
@
, sehingga garis miring (/
) tidak harus keluar. Lihat Contoh # 3 di sini: php.net/manual/en/function.preg-match.php .Jika kecepatan penting bagi Anda, coba ini. (Saya percaya ini adalah metode tercepat)
Hanya berfungsi untuk string dan jika $ haystack hanya 1 karakter
sumber
endsWithChar('','x')
tetapi hasilnya benarBerikut adalah dua fungsi yang tidak memperkenalkan string sementara, yang bisa berguna ketika jarum secara substansial besar:
sumber
endsWidth
harus dilakukanreturn $needle==='' || substr_compare(
... jadi itu berfungsi seperti yang diharapkan-strlen($needle)===0
yang, tanpa perbaikan, membuatendsWith('a','')
kembalifalse
substr_compare()
sebenarnya, jadi saya telah menambahkan PR untuk memperbaikinya :)endsWith('', 'foo')
memicu Peringatan: “substr_compare (): Posisi awal tidak boleh melebihi panjang string awal”. Mungkin itu bug lainsubstr_compare()
, tetapi untuk menghindarinya, Anda perlu melakukan pra-cek seperti ...|| (strlen($needle) <= strlen($haystack) && substr_compare(
...) === 0);
return $needle === '' || @substr_compare(
.. untuk menekan peringatan ini.Solusi tercepat dengan solusi ():
Benchmark:
Hasil Benchmark:
sumber
Saya menyadari ini telah selesai, tetapi Anda mungkin ingin melihat strncmp karena memungkinkan Anda untuk meletakkan panjang string untuk dibandingkan, jadi:
sumber
Anda bisa menggunakan
strpos
danstrrpos
sumber
strpos($sHaystack, $sNeedle) == 0
seperti inistrpos($sHaystack, $sNeedle) === 0
? Saya melihat bug, ketikafalse == 0
dievaluasitrue
.Inilah versi aman multi-byte dari jawaban yang diterima, itu berfungsi baik untuk string UTF-8:
sumber
startsWith
itu harus$length = mb_strlen($needle, 'UTF-8');
One-liner pendek dan mudah dipahami tanpa ekspresi reguler.
dimulai dengan () lurus ke depan.
endsWith () menggunakan strrev yang agak mewah dan lambat ():
sumber
Berfokus pada start dengan, jika Anda yakin string tidak kosong, menambahkan tes pada char pertama, sebelum perbandingan, strlen, dll., Mempercepat segalanya:
Itu entah bagaimana (20% -30%) lebih cepat. Menambahkan tes char lain, seperti $ haystack {1} === $ needle {1} tampaknya tidak mempercepat banyak hal, bahkan mungkin melambat.
===
tampaknya lebih cepat dari==
Operator Bersyarat(a)?b:c
tampaknya lebih cepat dariif(a) b; else c;
Bagi mereka yang bertanya "mengapa tidak menggunakan strpos?" menyebut solusi lain "pekerjaan yang tidak perlu"
Strpos cepat, tetapi itu bukan alat yang tepat untuk pekerjaan ini.
Untuk memahami, ini adalah sedikit simulasi sebagai contoh:
Apa yang dilakukan komputer "di dalam"?
Dengan asumsi strlen tidak mengulangi seluruh string (tetapi bahkan dalam kasus itu) ini tidak nyaman sama sekali.
sumber
Saya harap jawaban di bawah ini bisa efisien dan juga sederhana:
sumber
Saya biasanya berakhir dengan perpustakaan seperti garis bawah-php hari ini.
Perpustakaan penuh dengan fungsi praktis lainnya.
sumber
The jawabannya oleh mpen ini sangat menyeluruh, namun, sayangnya, patokan yang disediakan memiliki pengawasan yang sangat penting dan merugikan.
Karena setiap byte dalam jarum dan tumpukan jerami benar-benar acak, probabilitas bahwa pasangan jarum-tumpukan jerami akan berbeda pada byte pertama adalah 99,609375%, yang berarti bahwa, rata-rata, sekitar 99609 dari 100.000 pasangan akan berbeda pada byte pertama . Dengan kata lain, benchmark sangat bias terhadap
startswith
implementasi yang memeriksa byte pertama secara eksplisit, sepertistrncmp_startswith2
halnya.Jika loop menghasilkan tes diimplementasikan sebagai berikut:
hasil benchmark menceritakan kisah yang sedikit berbeda:
Tentu saja, tolok ukur ini mungkin masih tidak bias sempurna, tetapi ini menguji efisiensi algoritma ketika diberikan juga jarum yang cocok sebagian.
sumber
pendeknya:
sumber
Hanya rekomendasi:
Baris tambahan itu, yang membandingkan karakter pertama dari string, dapat membuat case palsu segera kembali , sehingga membuat banyak perbandingan Anda jauh lebih cepat (7x lebih cepat ketika saya mengukur). Dalam kasus yang sebenarnya Anda membayar hampir tidak ada harga dalam kinerja untuk satu baris jadi saya pikir itu layak termasuk. (Juga, dalam praktiknya, saat Anda menguji banyak string untuk suatu starting starting tertentu, sebagian besar perbandingan akan gagal karena dalam kasus tipikal Anda sedang mencari sesuatu.)
sumber
startsWith("123", "0")
memberikantrue
The
substr
fungsi dapat kembalifalse
dalam banyak kasus khusus, jadi di sini adalah versi saya, yang berkaitan dengan masalah ini:Tes (
true
berarti bagus):Selain itu,
substr_compare
fungsinya juga layak dicari. http://www.php.net/manual/en/function.substr-compare.phpsumber
Ini mungkin berhasil
Sumber: https://stackoverflow.com/a/4419658
sumber
Saya akan melakukannya seperti ini
sumber
Berdasarkan jawaban James Black, inilah ujungnya dengan versi:
Catatan: Saya telah menukar bagian if-else untuk fungsi James Black beginWith, karena strncasecmp sebenarnya adalah versi case-insensitive dari strncmp.
sumber
strrev()
ini kreatif tetapi sangat mahal, terutama jika Anda memiliki string katakan ... 100Kb.===
bukannya==
untuk memastikan.0
sama dengan banyak hal di PHP.Kenapa tidak mengikuti yang berikut?
Keluaran:
Perlu diingat,
strpos
akan mengembalikan false jika jarum tidak ditemukan di tumpukan jerami, dan akan mengembalikan 0 jika, dan hanya jika, jarum ditemukan di indeks 0 (AKA awal).Dan ini berakhir dengan:
Dalam skenario ini tidak perlu untuk fungsi beginWith () as
akan mengembalikan benar atau salah secara akurat.
Tampaknya aneh ini sesederhana ini dengan semua fungsi liar yang merajalela di sini.
sumber
strpos()
akan lambat kecuali saat cocok.strncmp()
akan jauh lebih baik dalam hal ini.Banyak jawaban sebelumnya juga akan berfungsi. Namun, ini mungkin sesingkat yang Anda bisa dan lakukan apa yang Anda inginkan. Anda hanya menyatakan bahwa Anda ingin 'mengembalikan yang benar'. Jadi saya memasukkan solusi yang mengembalikan boolean true / false dan tekstual true / false.
sumber
'true'
dan'false'
sebagai string, yang keduanyatrue
dalam arti boolean. Ini adalah pola yang baik untuk sesuatu seperti underhanded.xcott.com ;)Anda juga dapat menggunakan ekspresi reguler:
sumber
preg_quote($needle, '/')
.Tanpa-salin dan tanpa-intern-loop:
sumber
Inilah solusi yang efisien untuk PHP 4. Anda bisa mendapatkan hasil yang lebih cepat jika menggunakan PHP 5 dengan menggunakan
substr_compare
alih-alihstrcasecmp(substr(...))
.sumber
Anda dapat menggunakan fungsi fnmatch untuk ini.
sumber