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?


Apakah Anda bertanya tentang substring tetap, atau apakah Anda memerlukan ekspresi reguler (Saya agak bingung dengan penggunaan regextag)?
Tim Pietzcker


Bagaimana dengan memisahkan string ke array di sekitar spasi putih dan melakukan persimpangan array? stackoverflow.com/questions/1885557/…
giorgio79

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)


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.


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


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.


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


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.



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!


4
Tidak ada alasan matchkapan ada testmetode ... Periksa jawaban teratas.
Bergi
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.