Làm cách nào để kiểm tra xem một chuỗi có chứa một chuỗi con trong JavaScript không?


7427

Thông thường tôi sẽ mong đợi một String.contains()phương thức, nhưng dường như không có một phương pháp nào.

Một cách hợp lý để kiểm tra này là gì?

Câu trả lời:


13775

Giới thiệu ECMAScript 6 String.prototype.includes:

const string = "foo";
const substring = "oo";

console.log(string.includes(substring));

includes Mặc dù vậy, không có hỗ trợ Internet Explorer . Trong môi trường ECMAScript 5 trở lên, sử dụng String.prototype.indexOf, trả về -1 khi không thể tìm thấy chuỗi con:

var string = "foo";
var substring = "oo";

console.log(string.indexOf(substring) !== -1);


25
Tôi cũng không thích IE, nhưng nếu bạn có hai chức năng giống hệt nhau và một chức năng được hỗ trợ tốt hơn chức năng kia, tôi nghĩ bạn nên chọn chức năng nào được hỗ trợ tốt hơn? Vậy indexOf()là ...
rob74

3
Có thể làm một trường hợp tìm kiếm không nhạy cảm?
Eric McWinNEr

18
string.toUpperCase().includes(substring.toUpperCase())
Rodrigo Pinto

2
@EricMcWinNEr /regexpattern/i.test(str)-> i cờ là viết tắt của trường hợp không nhạy cảm
Code Maniac

Điều này dường như không hoạt động đối với tôi trong Google App Script.
Ryan

560

Có một String.prototype.includestrong ES6 :

"potato".includes("to");
> true

Lưu ý rằng điều này không hoạt động trong Internet Explorer hoặc một số trình duyệt cũ khác không có hoặc không hỗ trợ ES6. Để làm cho nó hoạt động trong các trình duyệt cũ, bạn có thể muốn sử dụng một bộ chuyển mã như Babel , thư viện shim như es6-shim hoặc polyfill này từ MDN :

if (!String.prototype.includes) {
  String.prototype.includes = function(search, start) {
    'use strict';
    if (typeof start !== 'number') {
      start = 0;
    }

    if (start + search.length > this.length) {
      return false;
    } else {
      return this.indexOf(search, start) !== -1;
    }
  };
}

3
Chỉ cần làm "potato".includes("to");và chạy nó qua Babel.
Derk Jan Speelman

1
bao gồm không được IE hỗ trợ một cách đáng buồn
Sweet Chilly Philly

@eliocs bạn có thể trả lời điều này. Tôi nhận được bất kỳ một tin nhắn. Cần thay đổi thông điệp stackoverflow.com/questions/61273744/ từ
sejn

1
một điểm cộng nữa cho nó là trường hợp nhạy cảm là tốt. "boot".includes("T")false
CD Jonatas

47

Một lựa chọn khác là KMP (Knuth Thẻ Morris, Pratt).

Các thuật toán KMP tìm kiếm cho một length- m substring trong một length- n chuỗi trong trường hợp xấu nhất O ( n + m ) thời gian, so với một trường hợp tồi tệ nhất của O ( nm ) cho các thuật toán ngây thơ, vì vậy sử dụng KMP thể là hợp lý nếu bạn quan tâm đến sự phức tạp thời gian trường hợp xấu nhất.

Đây là một triển khai JavaScript của Project Nayuki, được lấy từ https://www.nayuki.io/res/knuth-morris-pratt-opes-matching/kmp-opes-matcher.js :

// Searches for the given pattern string in the given text string using the Knuth-Morris-Pratt string matching algorithm.
// If the pattern is found, this returns the index of the start of the earliest match in 'text'. Otherwise -1 is returned.

function kmpSearch(pattern, text) {
  if (pattern.length == 0)
    return 0; // Immediate match

  // Compute longest suffix-prefix table
  var lsp = [0]; // Base case
  for (var i = 1; i < pattern.length; i++) {
    var j = lsp[i - 1]; // Start by assuming we're extending the previous LSP
    while (j > 0 && pattern.charAt(i) != pattern.charAt(j))
      j = lsp[j - 1];
    if (pattern.charAt(i) == pattern.charAt(j))
      j++;
    lsp.push(j);
  }

  // Walk through text string
  var j = 0; // Number of chars matched in pattern
  for (var i = 0; i < text.length; i++) {
    while (j > 0 && text.charAt(i) != pattern.charAt(j))
      j = lsp[j - 1]; // Fall back in the pattern
    if (text.charAt(i) == pattern.charAt(j)) {
      j++; // Next char matched, increment position
      if (j == pattern.length)
        return i - (j - 1);
    }
  }
  return -1; // Not found
}

console.log(kmpSearch('ays', 'haystack') != -1) // true
console.log(kmpSearch('asdf', 'haystack') != -1) // false


11
Đây là quá mức cần thiết nhưng dù sao cũng là một câu trả lời thú vị
Faissaloo
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.