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


163

Khá thẳng về phía trước. Trong javascript, tôi cần kiểm tra xem một chuỗi có chứa bất kỳ chuỗi con nào được giữ trong một mảng không.


Không có map()chức năng trong phiên bản HTML5-JavaScript mới phải không? Tôi nhớ đã đọc một cái gì đó về chủ đề đó ...
Martin Hennings

@Martin: Điểm hay, không mapnhiều bằng some. somesẽ giúp, nhưng bạn phải truyền cho nó một chức năng.
TJ Crowder

Câu trả lời:


222

Không có gì tích hợp sẽ làm điều đó cho bạn, bạn sẽ phải viết một hàm cho nó.

Nếu bạn biết các chuỗi không chứa bất kỳ ký tự nào đặc biệt trong các biểu thức thông thường, thì bạn có thể gian lận một chút, như thế này:

if (new RegExp(substrings.join("|")).test(string)) {
    // At least one match
}

... tạo ra một biểu thức chính quy đó là một loạt các thay thế cho các chuỗi con bạn đang tìm kiếm (ví dụ one|two) và kiểm tra xem liệu có phù hợp với bất kỳ trong số chúng không, nhưng nếu bất kỳ chuỗi con nào chứa bất kỳ ký tự nào là đặc biệt trong regexes ( *, [v.v.), trước tiên bạn phải thoát chúng và tốt hơn hết là bạn chỉ nên thực hiện vòng lặp nhàm chán.

Ví dụ trực tiếp:


Trong một bình luận về câu hỏi, Martin hỏi về Array.prototype.mapphương pháp mới trong ECMAScript5. mapkhông phải là rất nhiều giúp đỡ, nhưng somelà:

if (substrings.some(function(v) { return str.indexOf(v) >= 0; })) {
    // There's at least one
}

Ví dụ trực tiếp:

Bạn chỉ có nó trên các triển khai tuân thủ ECMAScript5, mặc dù nó không quan trọng đối với polyfill.


Cập nhật vào năm 2020 : someVí dụ có thể đơn giản hơn với chức năng mũi tên (ES2015 +) và bạn có thể sử dụng includesthay vì indexOf:

if (substrings.some(v => str.includes(v))) {
    // There's at least one
}

Ví dụ trực tiếp:

Hoặc thậm chí ném bindvào nó, mặc dù đối với tôi chức năng mũi tên dễ đọc hơn nhiều:

if (substrings.some(str.includes.bind(str))) {
    // There's at least one
}

Ví dụ trực tiếp:


2
"Nhớ bạn, nó có nghĩa là một số chi phí ..." nhưng không có gì phải quan tâm .
TJ Crowder

Bạn có thể mở rộng giải pháp trên bằng cách xóa tất cả các ký tự regex ngoại trừ '|' : new RegExp(substrings.join("|").replace(/[^\w\s^|]/gi, '')).test(string).
dùng007

việc sử dụng indexOf có thể quá mờ nhạt và mang lại một kết quả kỳ lạ. Nó có thể được đặt đơn giản để khớp với chuỗi bằng toán tử của bằng. ví dụ ('disconnect'.indexOf('connect') >= 0) === truenhưng('disconnect' === 'conenct') === false
kylewelsby

@halfcube: Hả? Tôi không hiểu bạn, tôi sợ. Không có gì trong câu trả lời ở trên cho thấy rằng 'disconnect' === 'connect'sẽ là bất cứ điều gì nhưng false. Ngoài ra, indexOfkhông mờ, nó thực sự được xác định rõ ràng.
TJ Crowder

indexOfsẽ phù hợp với cả hai disconnectconnecttrong trường hợp tôi đã trải qua, đây là hai trường hợp khác nhau tôi muốn trả về kết quả trong một điều kiện.
kylewelsby

54
var yourstring = 'tasty food'; // the string to check against


var substrings = ['foo','bar'],
    length = substrings.length;
while(length--) {
   if (yourstring.indexOf(substrings[length])!=-1) {
       // one of the substrings is in yourstring
   }
}

49

Giải pháp một dòng

substringsArray.some(substring=>yourBigString.includes(substring))

Trả về true\falsenếu chuỗi conexists\does'nt exist

Cần hỗ trợ ES6


Giải pháp tuyệt vời sử dụng các chức năng mũi tên
GuerillaRadio

7
Các bạn ... trở lại khi tôi còn là một đứa trẻ, chúng tôi phải sử dụng những thứ gọi là vòng lặp 'cho' và bạn phải sử dụng nhiều dòng và biết liệu mảng của bạn dựa trên 1 hay không, vâng ... một nửa thời gian bạn có nó sai và phải gỡ lỗi và tìm ra một bugger nhỏ gọi là 'i'.
aamarks

25
function containsAny(str, substrings) {
    for (var i = 0; i != substrings.length; i++) {
       var substring = substrings[i];
       if (str.indexOf(substring) != - 1) {
         return substring;
       }
    }
    return null; 
}

var result = containsAny("defg", ["ab", "cd", "ef"]);
console.log("String was found in substring " + result);

1
dễ hiểu nhất
Daryl H

Thêm vào đó, nó trả về sự xuất hiện đầu tiên của từ trong chuỗi, rất hữu ích. Không chỉ đúng / sai.
Kai Noack

20

Dành cho mọi người

Câu trả lời chắc chắn nên có.

const substrings = ['connect', 'ready'];
const str = 'disconnect';
if (substrings.some(v => str === v)) {
   // Will only return when the `str` is included in the `substrings`
}

2
hoặc ngắn hơn: if (basings.some (v => v === str)) {
kofifus

10
Lưu ý rằng đây là một câu trả lời cho một câu hỏi hơi khác, nó hỏi xem một chuỗi có chứa văn bản từ một chuỗi các chuỗi con hay không. Mã này kiểm tra nếu một chuỗi một trong các chuỗi con. Tôi phụ thuộc vào những gì có nghĩa là "chứa" tôi cho rằng.
fcrick

8
var str = "texttexttext";
var arr = ["asd", "ghj", "xtte"];
for (var i = 0, len = arr.length; i < len; ++i) {
    if (str.indexOf(arr[i]) != -1) {
        // str contains arr[i]
    }
}

chỉnh sửa: Nếu thứ tự của các bài kiểm tra không thành vấn đề, bạn có thể sử dụng điều này (chỉ với một biến vòng lặp):

var str = "texttexttext";
var arr = ["asd", "ghj", "xtte"];
for (var i = arr.length - 1; i >= 0; --i) {
    if (str.indexOf(arr[i]) != -1) {
        // str contains arr[i]
    }
}

Ví dụ đầu tiên của bạn không cần lenbiến, chỉ cần kiểm tra i < arr.length.
GreySage

3

Nếu mảng không lớn, bạn có thể lặp và kiểm tra chuỗi theo từng chuỗi con bằng cách sử dụng indexOf(). Ngoài ra, bạn có thể xây dựng một biểu thức chính quy với các chuỗi con thay thế, có thể hoặc có thể không hiệu quả hơn.


Giả sử chúng ta có một danh sách 100 chuỗi con. Cách nào sẽ hiệu quả hơn: RegExp hoặc loop?
Diyorbek Sadullayev

3

Hàm Javascript để tìm kiếm một mảng các thẻ hoặc từ khóa bằng chuỗi tìm kiếm hoặc một chuỗi các chuỗi tìm kiếm. (Sử dụng ES5 một số phương thức mảng và các hàm mũi tên ES6 )

// returns true for 1 or more matches, where 'a' is an array and 'b' is a search string or an array of multiple search strings
function contains(a, b) {
    // array matches
    if (Array.isArray(b)) {
        return b.some(x => a.indexOf(x) > -1);
    }
    // string match
    return a.indexOf(b) > -1;
}

Ví dụ sử dụng:

var a = ["a","b","c","d","e"];
var b = ["a","b"];
if ( contains(a, b) ) {
    // 1 or more matches found
}

2

Không phải tôi đang đề nghị bạn đi và mở rộng / sửa đổi Stringnguyên mẫu, nhưng đây là những gì tôi đã làm:

String.prototype.includes ()

String.prototype.includes = function (includes) {
    console.warn("String.prototype.includes() has been modified.");
    return function (searchString, position) {
        if (searchString instanceof Array) {
            for (var i = 0; i < searchString.length; i++) {
                if (includes.call(this, searchString[i], position)) {
                    return true;
                }
            }
            return false;
        } else {
            return includes.call(this, searchString, position);
        }
    }
}(String.prototype.includes);

console.log('"Hello, World!".includes("foo");',          "Hello, World!".includes("foo")           ); // false
console.log('"Hello, World!".includes(",");',            "Hello, World!".includes(",")             ); // true
console.log('"Hello, World!".includes(["foo", ","])',    "Hello, World!".includes(["foo", ","])    ); // true
console.log('"Hello, World!".includes(["foo", ","], 6)', "Hello, World!".includes(["foo", ","], 6) ); // false


2

Rút ra từ giải pháp của TJ Crowder, tôi đã tạo ra một nguyên mẫu để giải quyết vấn đề này:

Array.prototype.check = function (s) {
  return this.some((v) => {
    return s.indexOf(v) >= 0;
  });
};

2
substringsArray.every(substring=>yourBigString.indexOf(substring) === -1)

Để được hỗ trợ đầy đủ;)


2

Câu trả lời tốt nhất là ở đây: Đây là trường hợp không nhạy cảm là tốt

    var specsFilter = [.....];
    var yourString = "......";

    //if found a match
    if (specsFilter.some((element) => { return new RegExp(element, "ig").test(yourString) })) {
        // do something
    }

1

Sử dụng underscore.js hoặc lodash.js, bạn có thể thực hiện các thao tác sau trên một chuỗi các chuỗi:

var contacts = ['Billy Bob', 'John', 'Bill', 'Sarah'];

var filters = ['Bill', 'Sarah'];

contacts = _.filter(contacts, function(contact) {
    return _.every(filters, function(filter) { return (contact.indexOf(filter) === -1); });
});

// ['John']

Và trên một chuỗi duy nhất:

var contact = 'Billy';
var filters = ['Bill', 'Sarah'];

_.every(filters, function(filter) { return (contact.indexOf(filter) >= 0); });

// true

1

Đây là siêu muộn, nhưng tôi chỉ gặp phải vấn đề này. Trong dự án của riêng tôi, tôi đã sử dụng như sau để kiểm tra xem một chuỗi có nằm trong một mảng không:

["a","b"].includes('a')     // true
["a","b"].includes('b')     // true
["a","b"].includes('c')     // false

Bằng cách này, bạn có thể lấy một mảng được xác định trước và kiểm tra xem nó có chứa một chuỗi không:

var parameters = ['a','b']
parameters.includes('a')    // true

1

dựa trên câu trả lời của TJ Crowder

sử dụng RegExp đã thoát để kiểm tra sự xuất hiện "ít nhất một lần", của ít nhất một trong các chuỗi con.

function buildSearch(substrings) {
  return new RegExp(
    substrings
    .map(function (s) {return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');})
    .join('{1,}|') + '{1,}'
  );
}


var pattern = buildSearch(['hello','world']);

console.log(pattern.test('hello there'));
console.log(pattern.test('what a wonderful world'));
console.log(pattern.test('my name is ...'));


1

Nếu bạn đang làm việc với một danh sách dài các chuỗi con bao gồm các "từ" đầy đủ được phân tách bằng dấu cách hoặc bất kỳ ký tự phổ biến nào khác, bạn có thể thông minh một chút trong tìm kiếm của mình.

Đầu tiên, chia chuỗi của bạn thành các nhóm X, sau đó X + 1, sau đó X + 2, ..., tối đa Y. X và Y sẽ là số lượng từ trong chuỗi con của bạn với số lượng từ ít nhất và nhiều từ nhất tương ứng. Ví dụ: nếu X là 1 và Y là 4, "Alpha Beta Gamma Delta" trở thành:

"Alpha" "Beta" "Gamma" "Delta"

"Alpha Beta" "Gamma Beta" "Đồng bằng Gamma"

"Alpha Beta Gamma" "Beta Gamma Delta"

"Đồng bằng Gamma Alpha Beta"

Nếu X sẽ là 2 và Y là 3, thì bạn sẽ bỏ qua hàng đầu tiên và hàng cuối cùng.

Bây giờ bạn có thể tìm kiếm nhanh chóng trong danh sách này nếu bạn chèn nó vào Tập hợp (hoặc Bản đồ), nhanh hơn nhiều so với so sánh chuỗi.

Nhược điểm là bạn không thể tìm kiếm các chuỗi con như "ta Gamm". Tất nhiên bạn có thể cho phép điều đó bằng cách chia theo ký tự thay vì bằng từ, nhưng sau đó bạn thường cần xây dựng một Tập hợp lớn và thời gian / bộ nhớ dành cho việc đó vượt xa lợi ích.


1

Để được hỗ trợ đầy đủ (bổ sung để @ricca 's verions ).

wordsArray = ['hello', 'to', 'nice', 'day']
yourString = 'Hello. Today is a nice day'.toLowerCase()
result = wordsArray.every(w => yourString.includes(w))
console.log('result:', result)


0

Bạn có thể kiểm tra như thế này:

<!DOCTYPE html>
<html>
   <head>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
      <script>
         $(document).ready(function(){
         var list = ["bad", "words", "include"] 
         var sentence = $("#comments_text").val()

         $.each(list, function( index, value ) {
           if (sentence.indexOf(value) > -1) {
                console.log(value)
            }
         });
         });
      </script>
   </head>
   <body>
      <input id="comments_text" value="This is a bad, with include test"> 
   </body>
</html>

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.