Cara tercepat untuk memeriksa string berisi substring lain dalam JavaScript?

163

Saya bekerja dengan masalah kinerja pada JavaScript. Jadi saya hanya ingin bertanya: apa cara tercepat untuk memeriksa apakah sebuah string berisi substring lain (saya hanya perlu nilai boolean)? Bisakah Anda menyarankan ide dan contoh kode snippet Anda?

Đinh Hồng Châu
sumber
Apakah Anda bertanya tentang substring tetap, atau apakah Anda memerlukan ekspresi reguler (Saya agak bingung dengan penggunaan regextag)?
Tim Pietzcker
1
Posting ini akan sangat membantu .. stackoverflow.com/questions/1789945/javascript-string-contains
mtk
Bagaimana dengan memisahkan string ke array di sekitar spasi putih dan melakukan persimpangan array? stackoverflow.com/questions/1885557/…
giorgio79
jsben.ch/#/aWxtF
EscapeNetscape

Jawaban:

315

Anda memiliki dua kemungkinan:

  1. Ekspresi reguler :

    (new RegExp('word')).test(str)
    // or
    /word/.test(str)
  2. indexOf:

    str.indexOf('word') !== -1

Ekspresi reguler tampaknya lebih cepat (setidaknya di Chrome 10).

Uji kinerja - tumpukan jerami pendek
Uji kinerja - tumpukan jerami panjang


Pembaruan 2011:

Tidak bisa dikatakan dengan pasti metode mana yang lebih cepat. Perbedaan antara browser sangat besar. Sementara di Chrome 10 indexOftampaknya lebih cepat, di Safari 5, indexOfjelas lebih lambat daripada metode lainnya.

Anda harus melihat dan mencoba sendiri. Semua tergantung dari kebutuhan Anda. Misalnya pencarian case-insensitive jauh lebih cepat dengan ekspresi reguler.


Pembaruan 2018:

Hanya untuk menyelamatkan orang dari menjalankan tes itu sendiri, berikut adalah hasil saat ini untuk browser yang paling umum, persentase menunjukkan peningkatan kinerja dibandingkan hasil tercepat berikutnya (yang bervariasi antara browser):

Chrome: indexOf (~ 98% lebih cepat) <-- wow
Firefox: cached RegExp (~ 18% lebih cepat)
IE11: cached RegExp (~ 10% lebih cepat)
Edge: indexOf (~ 18% lebih cepat)
Safari: cached RegExp (~ 0,4% lebih cepat)

Perhatikan bahwa RegExp yang di- cache adalah: var r = new RegExp('simple'); var c = r.test(str);sebagai lawan dari:/simple/.test(str)

Felix Kling
sumber
3
Ini mungkin sedikit lebih cepat hanya jika teks-untuk-pencarian-dikenal sebelumnya (yaitu tidak disimpan dalam variabel) karena regex dibuat oleh mesin JavaScript selama waktu parse. Jika Anda ingin mencari string yang terkandung dalam variabel di dalam variabel string lain, indexOf adalah yang tercepat karena Anda harus membuat objek RegExp dan memproses string untuk keluar dari karakter khusus dll.
Stephen Chung
dari pengalaman, indexOf bisa lebih cepat untuk pencarian case-insensitive jika Anda menggunakan .toLowerCase pada apa pun yang Anda cari terlebih dahulu
Hayk Saakian
Saya sedang menulis aplikasi Office 2013, menggunakan Microsoft Office Javascript API, dan menggunakan indexOftidak berfungsi. Saya tidak yakin mengapa. Menggunakan Regex tidak. Ini adalah kasus tepi, tetapi orang lain mungkin mengalami masalah yang sama.
Andy Mercer
Adakah alasan substr () bukan salah satu solusi yang mungkin? Saya kira ini jauh lebih cepat daripada solusi RegEx dalam banyak situasi. Saya tidak tahu bagaimana membandingkannya dengan indexOf () (jadi jika Anda meninggalkannya karena selalu berkinerja lebih buruk daripada indexOf () maka tidak apa-apa, mungkin tambahkan catatan untuk efek itu.) EDIT: tautan JSperf ini menunjukkan beberapa yang menarik hasil. Versi singkat: indexOf () adalah yang tercepat dari semua metode, tetapi ini dapat bervariasi berdasarkan panjang string dan pola berulang.
Byson
1
@Bison: Anda hanya dapat menggunakan substr jika Anda sudah tahu ke mana harus mencari. Saya hanya fokus pada solusi generik.
Felix Kling
17

Apakah ini Bekerja untukmu?

string1.indexOf(string2) >= 0

Sunting: Ini mungkin tidak lebih cepat dari RegExp jika string2 berisi pola berulang. Pada beberapa browser, indexOf mungkin jauh lebih lambat daripada RegExp. Lihat komentar.

Sunting 2: RegExp mungkin lebih cepat daripada indexOf ketika string sangat panjang dan / atau berisi pola berulang. Lihat komentar dan jawaban @ Felix.

Stephen Chung
sumber
tetapi bagaimana hal ini dibandingkan dengan metode lain? Apakah ini yang tercepat, atau hanya salah satu dari sekian banyak metode untuk melakukannya?
Chii
Ini harus cepat karena diimplementasikan oleh JavaScript sendiri (yaitu menjalankan kode asli). Metode lain berdasarkan kode JavaScript akan lebih lambat. Jika Anda tahu string yang tepat, regex mungkin sedikit lebih cepat (karena mesin JavaScript tidak harus berjalan di rantai prototipe untuk menemukan .indexOf).
Stephen Chung
Jika Anda membutuhkan pencarian case-insensitive, maka Anda pasti perlu membuat objek dan panggilan RegExp test.
Stephen Chung
3
Baru saja menjalankan tes di Safari. indexOfadalah besarnya lebih lambat dari metode lainnya. Jadi sebenarnya tidak bisa dikatakan metode mana yang lebih cepat. Ini bervariasi dari browser ke browser.
Felix Kling
@ Feliks, itu pengamatan yang bagus (jangan pernah percaya apa pun sampai Anda benar-benar mencobanya sendiri)! Saya samar-samar mengingat sesuatu yang mengatakan dalam string dengan banyak pola berulang, regex's harus melakukan lebih cepat daripada implementasi perbandingan loop sederhana karena regex's dikompilasi ke dalam mesin negara dan dapat kembali melacak lebih cepat daripada loop sederhana - yang harus selalu mundur- melacak ke karakter berikutnya. +1 untuk melakukan percobaan dan menampilkan ini!
Stephen Chung
17

Tercepat

  1. (ES6) termasuk
    var string = "hello",
    substring = "lo";
    string.includes (substring);
  1. ES5 dan indexOf yang lebih lama
    var string = "hello",
    substring = "lo";
    string.indexOf (substring)! == -1;

http://jsben.ch/9cwLJ

masukkan deskripsi gambar di sini

Tính Ngô Quang
sumber
8

Dalam ES6, includes()metode ini digunakan untuk menentukan apakah satu string dapat ditemukan dalam string lain, kembali trueatau falsesesuai.

var str = 'To be, or not to be, that is the question.';

console.log(str.includes('To be'));       // true
console.log(str.includes('question'));    // true
console.log(str.includes('nonexistent')); // false

Inilah jsperf di antaranya

var ret = str.includes('one');

Dan

var ret = (str.indexOf('one') !== -1);

Seperti yang ditunjukkan pada jsperf, sepertinya keduanya berkinerja baik.

zangw
sumber
Bisakah saya menggunakan "regex" di dalam, seperti argumen yang disertakan? Seperti str.includes("x|y"):; cari literal "x" atau "y" dalam panggilan yang sama.
ptkato
@ Patrick, Per sertakan dokumen, Anda tidak dapat menggunakannya regexdi dalamnya. Satu jawaban untuk pertanyaan Anda,str.includes("x") || str.includes('y')
zangw
Sebagai hasil dari peningkatan JavaScript Chrome 59, indexOfsecara signifikan lebih cepat daripada includes(lebih dari 1600% lebih cepat). Tidak jelas bagaimana perbedaan 44 juta iterasi / detik dan 777+ juta i / detik memengaruhi kinerja dunia nyata, namun ponsel sepertinya cukup memberi manfaat yang indexOfseharusnya menjadi pilihan ideal.
Chad Levy
7

Saya telah menemukan bahwa menggunakan loop sederhana untuk, iterasi semua elemen dalam string dan membandingkan menggunakan charAtmelakukan lebih cepat daripada indexOfatau Regex. Kode dan bukti tersedia di JSPerf .

ETA: indexOfdan charAtkeduanya melakukan hal yang sama mengerikannya di Chrome Mobile menurut data Cakupan Browser yang terdaftar di jsperf.com

wpg4665
sumber
Aneh bahwa fungsi buatan tangan lebih baik daripada fungsi bawaan, tapi kurasa ini karena jarumnya hanya satu karakter. Masih ...
Moss
Diuji di Chrome Mobile 36.0.1985.57 di Apple iPad (iOS 7.1.1). IndexOf lebih cepat. Maaf
rpax
@rpax CharAt masih jauh lebih cepat secara signifikan di semua platform (berdasarkan sejarah dari jsperf) kecuali untuk Chrome Mobile, di mana kedua IndexOf dan CharAt sama-sama berkinerja sangat buruk dibandingkan dengan desktop.
wpg4665
1
Saya ingin melihat bagaimana kinerjanya di NodeJS, dan juga ini bukan contoh yang baik karena Anda hanya mencari satu karakter vs substring.
qodeninja
Ini bukan jawaban yang valid sama sekali. Anda tidak mencari substring, hanya kemunculan satu karakter tunggal
Henrik Myntti
3

Untuk menemukan string sederhana, menggunakan metode indexOf () dan menggunakan regex hampir sama: http://jsperf.com/substring - jadi pilih yang mana yang lebih mudah untuk ditulis.

Chii
sumber
1

Ini cara mudah untuk menggunakan .match()metode ke string.

var re = /(AND|OR|MAYBE)/;
var str = "IT'S MAYBE BETTER WAY TO USE .MATCH() METHOD TO STRING";
console.log('Do we found something?', Boolean(str.match(re)));

Semoga hari Anda menyenangkan, tuan!

Anton Danilchenko
sumber
4
Tidak ada alasan matchkapan ada testmetode ... Periksa jawaban teratas.
Bergi