Cách nhanh nhất để kiểm tra một chuỗi chứa một chuỗi con khác trong JavaScript?


163

Tôi đang làm việc với một vấn đề hiệu suất trên JavaScript. Vì vậy, tôi chỉ muốn hỏi: cách nhanh nhất để kiểm tra xem một chuỗi có chứa một chuỗi con khác không (tôi chỉ cần giá trị boolean)? Bạn có thể vui lòng đề xuất ý tưởng và mã đoạn mẫu của bạn?


Bạn đang hỏi về một chuỗi con cố định hay bạn cần một biểu thức chính quy (tôi hơi bối rối khi sử dụng regexthẻ)?
Tim Pietzcker


Làm thế nào về việc chia chuỗi thành một mảng xung quanh khoảng trắng và thực hiện một giao điểm mảng? stackoverflow.com/questions/1885557/
hy

Câu trả lời:


315

Bạn có hai possibilites:

  1. Biểu thức chính quy :

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

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

Biểu thức thông thường dường như nhanh hơn (ít nhất là trong Chrome 10).

Kiểm tra hiệu suất - ngắn haystack
Kiểm tra hiệu suất - haystack dài


Cập nhật 2011:

Không thể nói chắc chắn phương pháp nào nhanh hơn. Sự khác biệt giữa các trình duyệt là rất lớn. Mặc dù trong Chrome 10 indexOfdường như nhanh hơn, nhưng trong Safari 5, indexOfrõ ràng là chậm hơn bất kỳ phương pháp nào khác.

Bạn phải xem và cố gắng cho chính mình. Nó phụ thuộc vào nhu cầu của bạn. Ví dụ: tìm kiếm không phân biệt chữ hoa chữ thường nhanh hơn với các biểu thức thông thường.


Cập nhật 2018:

Chỉ để cứu mọi người khỏi tự chạy thử nghiệm, đây là kết quả hiện tại cho hầu hết các trình duyệt phổ biến, tỷ lệ phần trăm cho thấy hiệu suất tăng so với kết quả nhanh nhất tiếp theo (thay đổi giữa các trình duyệt):

Chrome: indexOf (nhanh hơn 98%) <-- wow
Firefox: RegExp được lưu trong bộ nhớ cache (nhanh hơn 18%)
IE11: RegExp được lưu trong bộ nhớ cache (nhanh hơn 10%)
Edge: indexOf (nhanh hơn 18%)
Safari: RegExp được lưu trong bộ nhớ cache (nhanh hơn 0,4%)

Lưu ý rằng RegExp được lưu trong bộ nhớ cache là: var r = new RegExp('simple'); var c = r.test(str);trái ngược với:/simple/.test(str)


3
Điều này có thể nhanh hơn một chút chỉ khi biết trước văn bản tìm kiếm văn bản (nghĩa là không được lưu trữ trong một biến) vì regex được tạo bởi công cụ JavaScript trong thời gian phân tích cú pháp. Nếu bạn muốn tìm kiếm một chuỗi chứa trong một biến bên trong một biến chuỗi khác, indexOf là nhanh nhất vì bạn cần tạo một đối tượng RegExp và xử lý chuỗi để thoát các ký tự đặc biệt, v.v.
Stephen Chung

từ kinh nghiệm, indexOf có thể nhanh hơn cho tìm kiếm không phân biệt chữ hoa chữ thường nếu bạn sử dụng .toLowerCase cho bất cứ điều gì bạn đang tìm kiếm đầu tiên
Hayk Saakian

Tôi đang viết Ứng dụng Office 2013, sử dụng API Office Javascript của Microsoft và sử dụng indexOfkhông hoạt động. Tôi cung không chăc tại sao. Sử dụng Regex mặc dù không. Đây là một trường hợp cạnh, nhưng những người khác có thể gặp vấn đề tương tự.
Andy Mercer

Bất kỳ lý do chất nền () không phải là một trong những giải pháp có thể? Tôi đoán nó nhanh hơn nhiều so với giải pháp RegEx trong nhiều tình huống. Tôi không biết làm thế nào nó so sánh với indexOf () (vì vậy nếu bạn bỏ nó đi vì nó luôn hoạt động kém hơn indexOf () thì tốt, có thể thêm một ghi chú cho hiệu ứng đó.) EDIT: liên kết JSperf này cho thấy một số thú vị các kết quả. Phiên bản ngắn: indexOf () là phương thức nhanh nhất trong tất cả các phương thức, nhưng điều này có thể thay đổi dựa trên độ dài chuỗi và bất kỳ mẫu lặp lại nào.
Byson

1
@Bison: bạn chỉ có thể sử dụng chất nền nếu bạn đã biết tìm ở đâu. Tôi chỉ tập trung vào các giải pháp chung chung.
Felix Kling

17

công việc này là dành cho bạn?

string1.indexOf(string2) >= 0

Chỉnh sửa: Điều này có thể không nhanh hơn RegExp nếu chuỗi2 chứa các mẫu lặp lại. Trên một số trình duyệt, indexOf có thể chậm hơn nhiều so với RegExp. Xem ý kiến.

Chỉnh sửa 2: RegExp có thể nhanh hơn indexOf khi các chuỗi rất dài và / hoặc chứa các mẫu lặp lại. Xem bình luận và câu trả lời của @ Felix.


nhưng làm thế nào để so sánh với các phương pháp khác? Đây có phải là nhanh nhất, hay nó chỉ là một trong nhiều phương pháp để làm như vậy?
Chii

Việc này phải nhanh vì nó được JavaScript triển khai (tức là nó chạy mã gốc). Bất kỳ phương pháp nào khác dựa trên mã JavaScript sẽ chậm hơn. Nếu bạn biết chuỗi chính xác, regex có thể nhanh hơn một chút (vì công cụ JavaScript không phải đi theo chuỗi nguyên mẫu để tìm .indexOf).
Stephen Chung

Nếu bạn cần tìm kiếm không phân biệt chữ hoa chữ thường, thì bạn chắc chắn cần phải xây dựng một đối tượng RegExp và gọi test.
Stephen Chung

3
Chỉ cần chạy thử nghiệm trong Safari. indexOflà một cường độ chậm hơn bất kỳ phương pháp nào khác. Vì vậy, nó thực sự không thể nói phương pháp nào là nhanh hơn. Nó thay đổi từ trình duyệt để trình duyệt.
Felix Kling

@Felix, đó là một quan sát tốt (không bao giờ tin bất cứ điều gì cho đến khi bạn thực sự tự mình thử nó)! Tôi mơ hồ nhớ một cái gì đó nói trong chuỗi có nhiều mẫu lặp đi lặp lại, regex sẽ thực hiện nhanh hơn so với triển khai so sánh vòng lặp đơn giản vì regex được biên dịch vào các máy trạng thái và nó có thể theo dõi nhanh hơn nhiều so với các vòng lặp đơn giản - vốn luôn phải quay lại theo dõi nhân vật tiếp theo +1 để thực hiện thử nghiệm và đưa ra điều này!
Stephen Chung

17

Nhanh nhất

  1. (ES6) bao gồm
    var chuỗi = "xin chào",
    chuỗi con = "lo";
    string.includes (chuỗi con);
  1. ES5 trở lên indexOf
    var chuỗi = "xin chào",
    chuỗi con = "lo";
    chuỗi.indexOf (chuỗi con)! == -1;

http://jsben.ch/9cwLJ

nhập mô tả hình ảnh ở đây


8

Trong ES6, includes()phương thức được sử dụng để xác định xem một chuỗi có thể được tìm thấy trong một chuỗi khác, trả về truehoặc falsekhi thích hợp.

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

Đây là jsperf giữa

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

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

Theo kết quả được hiển thị trong jsperf, có vẻ như cả hai đều hoạt động tốt.


Tôi có thể sử dụng "regex" bên trong, bao gồm 'đối số không? Thích : str.includes("x|y"); tìm kiếm các chữ "x" hoặc "y" trong cùng một cuộc gọi.
ptkato

@Patrick, mỗi tài liệu bao gồm, bạn không thể sử dụng regexnó. Một cách giải quyết cho câu hỏi của bạn,str.includes("x") || str.includes('y')
zangw

Do kết quả của các cải tiến JavaScript của Chrome 59, indexOfnhanh hơn đáng kể so với includes( nhanh hơn 1600%). Không rõ mức chênh lệch 44 triệu lần / giây và 777 triệu i / giây ảnh hưởng đến hiệu suất trong thế giới thực, tuy nhiên di động có thể mang lại lợi ích đủ để indexOftrở thành lựa chọn lý tưởng.
Chad Levy

7

Tôi đã thấy rằng sử dụng một vòng lặp đơn giản, lặp lại tất cả các phần tử trong chuỗi và so sánh việc sử dụng hiệu suất charAtnhanh hơn indexOfhoặc Regex. Mã và bằng chứng có sẵn tại JSPerf .

ETA: indexOfcharAtcả hai đều hoạt động khủng khiếp tương tự trên Chrome Mobile theo dữ liệu Phạm vi trình duyệt được liệt kê trên jsperf.com


Kỳ lạ là một chức năng làm bằng tay tốt hơn chức năng tích hợp trong một, nhưng tôi đoán điều này là do kim chỉ có một ký tự. Vẫn ...
Rêu

Đã thử nghiệm trong Chrome Mobile 36.0.1985.57 trên iPad của Apple (iOS 7.1.1). IndexOf nhanh hơn. Xin lỗi
rpax

@rpax CharAt vẫn nhanh hơn đáng kể trên tất cả các nền tảng (dựa trên lịch sử từ jsperf) ngoại trừ Chrome Mobile, nơi cả IndexOf và CharAt đều hoạt động rất kém so với máy tính để bàn.
wpg4665

1
Tôi muốn xem cách nó hoạt động trong NodeJS, và đây cũng không thực sự là một ví dụ hay vì bạn chỉ tìm kiếm một ký tự và một chuỗi con.
qodeninja

Đây không phải là một câu trả lời hợp lệ cả. Bạn không tìm kiếm một chuỗi con, chỉ có sự xuất hiện của một ký tự duy nhất
Henrik Myntti

3

Để tìm một chuỗi đơn giản, sử dụng phương thức indexOf () và sử dụng regex khá giống nhau: http://jsperf.com/subopes - vì vậy hãy chọn chuỗi nào có vẻ dễ viết hơn.



1

Đó là cách dễ dàng để sử dụng .match()phương thức để xâu chuỗi.

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)));

Chúc bạn một ngày tốt lành, thưa ngài!


4
Không có lý do gì matchkhi có một testphương pháp. Kiểm tra câu trả lời hàng đầu.
Bergi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.