Dalam javascript, apakah ada yang setara dengan String.indexOf () yang mengambil ekspresi reguler alih-alih string untuk parameter pertama pertama sementara masih mengizinkan parameter kedua?
Saya perlu melakukan sesuatu seperti
str.indexOf(/[abc]/ , i);
dan
str.lastIndexOf(/[abc]/ , i);
Meskipun String.search () menggunakan regexp sebagai parameter, itu tidak memungkinkan saya untuk menentukan argumen kedua!
Sunting:
Ini ternyata lebih sulit daripada yang saya pikir awalnya jadi saya menulis fungsi uji kecil untuk menguji semua solusi yang disediakan ... ia menganggap regexIndexOf dan regexLastIndexOf telah ditambahkan ke objek String.
function test (str) {
var i = str.length +2;
while (i--) {
if (str.indexOf('a',i) != str.regexIndexOf(/a/,i))
alert (['failed regexIndexOf ' , str,i , str.indexOf('a',i) , str.regexIndexOf(/a/,i)]) ;
if (str.lastIndexOf('a',i) != str.regexLastIndexOf(/a/,i) )
alert (['failed regexLastIndexOf ' , str,i,str.lastIndexOf('a',i) , str.regexLastIndexOf(/a/,i)]) ;
}
}
dan saya menguji sebagai berikut untuk memastikan bahwa setidaknya untuk satu karakter regexp, hasilnya sama seperti jika kita menggunakan indexOf
// Cari a diantara
tes xes ('xxx');
test ('axx');
test ('xax');
test ('xxa');
test ('axa');
test ('xaa');
test ('aax');
test ('aaa');
sumber
|
di dalam[ ]
cocok dengan karakter literal|
. Anda mungkin bermaksud[abc]
.Jawaban:
Menggabungkan beberapa pendekatan yang telah disebutkan (indexOf jelas agak sederhana), saya pikir ini adalah fungsi yang akan melakukan trik:
Jelas, memodifikasi objek String bawaan akan mengirimkan bendera merah untuk kebanyakan orang, tetapi ini mungkin satu kali ketika itu bukan masalah besar; cukup sadari itu.
UPDATE: Diedit
regexLastIndexOf()
sehingga sepertinya menirulastIndexOf()
sekarang. Tolong beri tahu saya jika masih gagal dan dalam keadaan apa.PEMBARUAN: Lulus semua tes yang ditemukan di dalam komentar di halaman ini, dan milik saya. Tentu saja, itu tidak berarti itu anti peluru. Setiap umpan balik dihargai.
sumber
regexLastIndexOf
hanya akan mengembalikan indeks pertandingan yang tidak tumpang tindih terakhir.regex.lastIndex = result.index + 1;
daripadaregex.lastIndex = ++nextStop;
. Ini akan berlanjut ke pertandingan berikutnya jauh lebih cepat semoga tanpa kehilangan hasil apa pun.Contoh
String
konstruktor memiliki.search()
metode yang menerima RegExp dan mengembalikan indeks pertandingan pertama.Untuk memulai pencarian dari posisi tertentu (memalsukan parameter kedua
.indexOf()
), Anda dapatslice
mematikani
karakter pertama :Tapi ini akan mendapatkan indeks dalam string yang lebih pendek (setelah bagian pertama dipotong) sehingga Anda ingin kemudian menambahkan panjang bagian yang dipotong (
i
) ke indeks yang dikembalikan jika tidak-1
. Ini akan memberi Anda indeks dalam string asli:sumber
function regexIndexOf(text, offset) { var initial = text.substr(offset).search(/re/); if(initial >= 0) { initial += offset; } return initial; }
Saya punya versi singkat untuk Anda. Ini bekerja dengan baik untuk saya!
Dan jika Anda menginginkan versi prototipe:
Sunting : jika Anda ingin menambahkan dukungan untuk dariIndex
Untuk menggunakannya, sesederhana ini:
sumber
startIndex
parameter seperti biasaindeoxOf
danlastIndexOf
lakukan.startIndex
(ataufromIndex
). Semoga ini bisa membantu!lastIndexOfRegex
juga harus menambahkan kembali nilaifromIndex
ke hasil."aRomeo Romeo".indexOfRegex(new RegExp("\\bromeo", 'gi'));
Hasilnya akan menjadi 1 ketika seharusnya menjadi 7, karena indexOf akan mencari pertama kali "romeo" muncul, tidak peduli apakah itu di awal kata atau tidak.Menggunakan:
Lihat dokumentasi di sini.
sumber
0
, dan telah diposting ... tujuh tahun kemudian.Berdasarkan jawaban BaileyP. Perbedaan utama adalah bahwa metode ini kembali
-1
jika polanya tidak cocok.Sunting: Terima kasih atas jawaban Jason Bunting, saya mendapat ide. Mengapa tidak memodifikasi
.lastIndex
properti regex? Padahal ini hanya akan berfungsi untuk pola dengan bendera global (/g
).Sunting: Diperbarui untuk lulus test case.
sumber
Anda bisa menggunakan substr.
sumber
RexExp
contoh memiliki lastIndex properti sudah (jika mereka global) dan apa yang saya lakukan adalah menyalin ekspresi reguler, memodifikasi sedikit untuk memenuhi tujuan kita,exec
-ing pada string dan melihatlastIndex
. Ini pasti akan lebih cepat daripada mengulang pada string. (Anda punya cukup banyak contoh cara memasukkan ini ke prototipe string, kan?)Anda juga bisa membuat prototipe fungsi ke objek RegExp:
Penjelasan singkat tentang bagaimana saya memodifikasi
RegExp
: KarenaindexOf
saya hanya perlu memastikan bahwa bendera global diatur. UntuklastIndexOf
saya menggunakan pandangan negatif ke depan untuk menemukan kejadian terakhir kecualiRegExp
sudah cocok pada akhir string.sumber
Ini tidak asli, tetapi Anda tentu dapat menambahkan fungsi ini
Saya tidak sepenuhnya menguji metode ini, tetapi mereka tampaknya bekerja sejauh ini.
sumber
Setelah semua solusi yang diajukan gagal dalam pengujian saya dengan satu atau lain cara, (sunting: ada yang diperbarui untuk lulus tes setelah saya menulis ini) Saya menemukan implementasi mozilla untuk Array.indexOf dan Array.lastIndexOf
Saya menggunakan itu untuk mengimplementasikan versi saya dari String.prototype.regexIndexOf dan String.prototype.regexLastIndexOf sebagai berikut:
Mereka tampaknya lulus fungsi tes yang saya berikan dalam pertanyaan.
Jelas mereka hanya berfungsi jika ekspresi reguler cocok dengan satu karakter tetapi itu sudah cukup untuk tujuan saya karena saya akan menggunakannya untuk hal-hal seperti ([abc], \ s, \ W, \ D)
Saya akan terus memantau pertanyaan jika seseorang menyediakan implementasi generik yang lebih baik / lebih cepat / lebih bersih / lebih umum yang berfungsi pada ekspresi reguler apa pun.
sumber
Saya membutuhkan
regexIndexOf
fungsi juga untuk sebuah array, jadi saya memprogramnya sendiri. Namun saya ragu, itu dioptimalkan, tetapi saya kira itu harus bekerja dengan baik.sumber
Dalam kasus-kasus sederhana tertentu, Anda dapat menyederhanakan pencarian mundur Anda dengan menggunakan split.
Ini memiliki beberapa masalah serius:
Tapi di sisi baiknya, kode itu jauh lebih sedikit. Untuk regex dengan panjang konstan yang tidak dapat tumpang tindih (seperti
/\s\w/
untuk menemukan batas kata) ini cukup baik.sumber
Untuk data dengan kecocokan yang jarang, menggunakan string.search adalah yang tercepat di seluruh browser. Ini mengiris kembali string setiap iterasi ke:
Untuk data yang padat saya membuat ini. Ini kompleks dibandingkan dengan metode eksekusi, tetapi untuk data yang padat, ini 2-10x lebih cepat daripada setiap metode lain yang saya coba, dan sekitar 100x lebih cepat dari solusi yang diterima. Poin utamanya adalah:
Regex baru dijalankan dan hasil dari eksekutif tersebut, atau eksekutif pertama, dikembalikan;
jsPerf metode
Saya tidak mengerti tujuan dari tes di bagian atas. Situasi yang memerlukan regex tidak mungkin dibandingkan dengan panggilan ke indexOf, yang saya pikir adalah titik membuat metode di tempat pertama. Untuk mendapatkan lulus ujian, lebih masuk akal untuk menggunakan 'xxx + (?! x)', daripada menyesuaikan cara regex iterates.
sumber
Indeks terakhir Jason Bunting tidak berfungsi. Milik saya tidak optimal, tetapi berhasil.
sumber
Masih belum ada metode asli yang melakukan tugas yang diminta.
Berikut adalah kode yang saya gunakan. Ini meniru perilaku String.prototype.indexOf dan String.prototype.lastIndexOf metode tetapi mereka juga menerima regexp sebagai argumen pencarian selain string yang mewakili nilai untuk mencari.
Ya itu cukup panjang karena jawabannya berusaha untuk mengikuti standar saat ini sedekat mungkin dan tentu saja mengandung jumlah JSDOC yang masuk akal komentar . Namun, setelah diperkecil, kodenya hanya 2.27k dan sekali di-gzip untuk transmisi hanya 1023 byte.
2 metode yang ditambahkan ini
String.prototype
(menggunakan Object.defineProperty jika tersedia) adalah:searchOf
searchLastOf
Ini melewati semua tes yang diposting OP dan juga saya telah menguji rutinitas cukup menyeluruh dalam penggunaan sehari-hari saya, dan telah berusaha untuk memastikan bahwa mereka bekerja di berbagai lingkungan, tetapi umpan balik / masalah selalu diterima.
sumber
Jika Anda mencari lastIndex lookup yang sangat sederhana dengan RegExp dan tidak peduli apakah itu meniru lastIndexOf ke detail terakhir, ini mungkin menarik perhatian Anda.
Saya hanya membalikkan string, dan mengurangi indeks kemunculan pertama dari panjang - 1. Kebetulan lulus tes saya, tapi saya pikir mungkin ada masalah kinerja dengan string panjang.
sumber
Saya menggunakan
String.prototype.match(regex)
yang mengembalikan array string dari semua kecocokan yang ditemukan dari yang diberikanregex
dalam string (info lebih lanjut lihat di sini ):sumber
Gunakan persamaan reguler standar:
sumber
Yah, karena Anda hanya ingin mencocokkan posisi karakter , regex mungkin berlebihan.
Saya kira semua yang Anda inginkan adalah, alih-alih "temukan dulu karakter ini", cari saja dulu karakter ini.
Ini tentu saja adalah jawaban yang sederhana, tetapi melakukan apa yang ingin dilakukan pertanyaan Anda, meskipun tanpa bagian regex (karena Anda tidak menjelaskan mengapa khusus itu harus menjadi sebuah regex)
sumber