Как проверить, содержит ли строка текст из массива подстрок в JavaScript?

Довольно прямо вперед. В javascript мне нужно проверить, содержит ли строка какие-либо подстроки, содержащиеся в массиве.

24 ответа

Решение

Там нет ничего встроенного, что сделает это для вас, вам придется написать функцию для этого.

Если вы знаете, что строки не содержат символов, которые являются специальными в регулярных выражениях, то вы можете немного обмануть, например так:

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

... который создает регулярное выражение, представляющее собой серию чередований подстрок, которые вы ищете (например, one|two) и проверяет, есть ли совпадения для любого из них, но содержит ли какая-либо из подстрок символы, которые являются специальными в регулярных выражениях (*, [и т. д.), вам нужно сначала избежать их, и вам лучше просто делать скучный цикл.

Бесплатный пример из жизни


Обновление:

В комментарии к вопросу Martin Hennings спрашивает о новом Array#map функция в ECMAScript5. map не так уж много помочь, но some является:

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

Живой пример (работает только в современных браузерах)

Имейте в виду, это означает некоторые накладные расходы, и вы имеете их только в ECMAScript5-совместимых реализациях (например, не в IE7 или более ранних, например; возможно, даже не в IE8), но все же, если вы действительно в этом стиле программирования.. (И вы могли бы использовать прокладку ECMAScript5, эту или любую из нескольких других.)

Решение одной линии

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

Возвращает true\false если подстрока exists\does'nt exist

Требуется поддержка ES6

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

Для людей, гуглящих,

Твердый ответ должен быть.

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

Вот что (ИМО) , безусловно, лучшее решение. Это современное (ES6) решение, которое:

  • работоспособен (одна строка!)
  • избегает циклов for
  • в отличие от some() функция, которая используется в других ответах, она не просто возвращает логическое значение (истина / ложь)
  • вместо этого он либо возвращает подстроку (если она была найдена в массиве), либо возвращает undefined
  • идет еще дальше и позволяет вам выбрать, нужны ли вам частичные совпадения подстрок (примеры ниже)

Наслаждайтесь! И, пожалуйста, проголосуйте, если это помогло вам, мне потребовалось много времени, чтобы усовершенствовать этот ответ! Грасиас:)



const arrayOfStrings = ['abc', 'def', 'xyz'];
const str = 'abc';
const found = arrayOfStrings.find(v => (str === v));

Вот, foundв этом случае будет установлено значение "abc". Это будет работать для точных совпадений строк.

Если вместо этого вы используете:

const found = arrayOfStrings.find(v => str.includes(v));

Снова, foundв этом случае будет установлено значение "abc". Это не допускает частичных совпадений, поэтому, если для str задано значение 'ab',found будет неопределенным.


И, если вы хотите, чтобы частичные совпадения работали, просто переверните его, чтобы вы сделали:
const found = arrayOfStrings.find(v => v.includes(str));

вместо. Итак, если str было установлено на 'ab',found будет установлено значение "abc".

Очень просто!



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]
    }
}

edit: если порядок тестов не имеет значения, вы можете использовать это (только с одной переменной цикла):

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]
    }
}
      const str = 'Does this string have one or more strings from the array below?';
const arr = ['one', 'two', 'three'];

const contains = arr.some(element => {
  if (str.includes(element)) {
    return true;
  }
  return false;
});

console.log(contains); // true

Для полной поддержки (в дополнение к версиям @ricca).

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

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

За полную поддержку;)

Это супер поздно, но я только столкнулся с этой проблемой. В моем собственном проекте я использовал следующее, чтобы проверить, была ли строка в массиве:

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

Таким образом, вы можете взять предопределенный массив и проверить, содержит ли он строку:

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

Лучший ответ здесь: это также с учетом регистра

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

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

Функция Javascript для поиска в массиве тегов или ключевых слов, используя строку поиска или массив строк поиска. (Использует ES5 некоторый метод массива и функции стрелок 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;
}

Пример использования:

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

Если массив не большой, вы можете просто зациклить и проверить строку для каждой подстроки в отдельности, используя indexOf(), В качестве альтернативы вы можете создать регулярное выражение с подстрокой в ​​качестве альтернативы, что может быть или не быть более эффективным.

Не то чтобы я предлагал вам пойти и расширить / изменить String прототип, но это то, что я сделал:

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

Опираясь на ответ TJ Crowder

использование экранированного RegExp для проверки на наличие "хотя бы одного" хотя бы одной из подстрок.

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

Рисуя решение TJ Crowder, я создал прототип для решения этой проблемы:

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

У меня была такая проблема. У меня был URL-адрес, я хотел проверить, заканчивается ли ссылка форматом изображения или другим форматом файла, имеющим массив формата изображений. Вот что я сделал:

      const imagesFormat = ['.jpg','.png','.svg']
const link = "https://res.cloudinary.com/***/content/file_padnar.pdf"
const isIncludes = imagesFormat.some(format => link.includes(format))
    
// false
convert_to_array = function (sentence) {
     return sentence.trim().split(" ");
};

let ages = convert_to_array ("I'm a programmer in javascript writing script");

function confirmEnding(string) {
let target = "ipt";
    return  (string.substr(-target.length) === target) ? true : false;
}

function mySearchResult() {
return ages.filter(confirmEnding);
}

mySearchResult();

вы можете проверить это и вернуть массив совпадающих слов с помощью фильтра

Используя underscore.js или lodash.js, вы можете сделать следующее для массива строк:

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']

И на одной строке:

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

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

// true

Если вы работаете с длинным списком подстрок, состоящим из полных "слов", разделенных пробелами, или любого другого общего символа, вы можете быть немного умнее в своем поиске.

Сначала разделите вашу строку на группы X, затем X+1, затем X+2, ..., вплоть до Y. X и Y должны быть количеством слов в вашей подстроке с наименьшим и наибольшим количеством слов соответственно. Например, если X равно 1, а Y равно 4, "Alpha Beta Gamma Delta" станет:

"Альфа" "Бета" "Гамма" "Дельта"

"Альфа-Бета" "Бета-Гамма" "Гамма-дельта"

"Альфа-бета-гамма" "Бета-гамма-дельта"

"Альфа-Бета Гамма Дельта"

Если бы X было 2, а Y было бы 3, вы бы опускали первую и последнюю строки.

Теперь вы можете быстро искать в этом списке, если вставляете его в Set (или Map), намного быстрее, чем при сравнении строк.

Обратной стороной является то, что вы не можете искать такие подстроки, как "ta Gamm". Конечно, вы можете допустить это, разделив по символам, а не по словам, но тогда вам часто придется создавать массивный Set, и время / память, потраченные на это, перевешивают преимущества.

Проверить можно так:

<!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>
let obj = [{name : 'amit'},{name : 'arti'},{name : 'sumit'}];
let input = 'it';

Использовать фильтр:

obj.filter((n)=> n.name.trim().toLowerCase().includes(input.trim().toLowerCase()))

Другие вопросы по тегам