Довольно прямолинейно. В javascript мне нужно проверить, содержит ли строка какие-либо подстроки, содержащиеся в массиве.
Как проверить, содержит ли строка текст из массива подстрок в JavaScript?
Ответы (19)
Нет ничего встроенного, что могло бы сделать это за вас, вам придется написать для этого функцию.
Если вы знаете, что строки не содержат каких-либо специальных символов в регулярных выражениях, вы можете немного схитрить, например:
if (new RegExp(substrings.join("|")).test(string)) {
// At least one match
}
... который создает регулярное выражение, представляющее собой серию чередований для искомых подстрок (например, one|two
), и проверяет, есть ли совпадения для какой-либо из них, но если какая-либо из подстроки содержат любые символы, которые являются специальными в регулярных выражениях (*
, [
и т. д.), вам придется сначала их экранировать, и вместо этого вам лучше просто выполнить скучный цикл. Для получения информации о том, как их избежать, см. ответы на этот вопрос.
Живой пример:
var substrings = ["one", "two", "three"];
var str;
// Setup
console.log("Substrings: " + substrings.join(","));
// Try it where we expect a match
str = "this has one";
if (new RegExp(substrings.join("|")).test(str)) {
console.log("Match using '" + str + "'");
} else {
console.log("No match using '" + str + "'");
}
// Try it where we DON'T expect a match
str = "this doesn't have any";
if (new RegExp(substrings.join("|")).test(str)) {
console.log("Match using '" + str + "'");
} else {
console.log("No match using '" + str + "'");
}
В комментарии к вопросу Мартин спрашивает о новом методе Array.prototype.map
в ECMAScript5. map
не очень помогает, но some
:
if (substrings.some(function(v) { return str.indexOf(v) >= 0; })) {
// There's at least one
}
Живой пример:
var substrings = ["one", "two", "three"];
var str;
// Setup
console.log("Substrings: " + substrings.join(","));
// Try it where we expect a match
str = "this has one";
if (substrings.some(function(v) { return str.indexOf(v) >= 0; })) {
console.log("Match using '" + str + "'");
} else {
console.log("No match using '" + str + "'");
}
// Try it where we DON'T expect a match
str = "this doesn't have any";
if (substrings.some(function(v) { return str.indexOf(v) >= 0; })) {
console.log("Match using '" + str + "'");
} else {
console.log("No match using '" + str + "'");
}
Он есть только в реализациях, совместимых с ECMAScript5, хотя полифил - тривиально.
Обновление в 2020 году: пример some
можно упростить с помощью функции стрелки (ES2015 +), и вы можете использовать includes
вместо indexOf
:
if (substrings.some(v => str.includes(v))) {
// There's at least one
}
Живой пример:
const substrings = ["one", "two", "three"];
let str;
// Setup
console.log("Substrings: " + substrings.join(","));
// Try it where we expect a match
str = "this has one";
if (substrings.some(v => str.includes(v))) {
console.log("Match using '" + str + "'");
} else {
console.log("No match using '" + str + "'");
}
// Try it where we DON'T expect a match
str = "this doesn't have any";
if (substrings.some(v => str.includes(v))) {
console.log("Match using '" + str + "'");
} else {
console.log("No match using '" + str + "'");
}
Или даже бросить на него bind
, хотя для меня стрелочная функция намного читабельнее:
if (substrings.some(str.includes.bind(str))) {
// There's at least one
}
Живой пример:
const substrings = ["one", "two", "three"];
let str;
// Setup
console.log("Substrings: " + substrings.join(","));
// Try it where we expect a match
str = "this has one";
if (substrings.some(str.includes.bind(str))) {
console.log("Match using '" + str + "'");
} else {
console.log("No match using '" + str + "'");
}
// Try it where we DON'T expect a match
str = "this doesn't have any";
if (substrings.some(str.includes.bind(str))) {
console.log("Match using '" + str + "'");
} else {
console.log("No match using '" + str + "'");
}
new RegExp(substrings.join("|").replace(/[^\w\s^|]/gi, '')).test(string)
.
- person user007; 09.05.2015
('disconnect'.indexOf('connect') >= 0) === true
но ('disconnect' === 'conenct') === false
- person kylewelsby; 13.06.2015
'disconnect' === 'connect'
будет чем угодно, кроме false
. Кроме того, indexOf
не является расплывчатым, он действительно очень четко определен.
- person T.J. Crowder; 13.06.2015
indexOf
будет соответствовать как disconnect
, так и connect
, где в случае, который я испытал, это два разных случая, для которых я хочу вернуть результаты в условном выражении.
- person kylewelsby; 15.06.2015
return str === v;
, а не return str.indexOf(v) >= 0;
. Но они специально ищут подстроки.
- person T.J. Crowder; 15.06.2015
/g
. Иногда я получаю истину, а иногда ложь, даже при повторной проверке в отладчике webstorm во время паузы ... и я также вижу в узле.
- person chovy; 24.02.2017
g
имеют состояние, которое они сохраняют от одного использования до следующего, что, вероятно, является тем, о чем вы спотыкаетесь.
- person T.J. Crowder; 24.02.2017
.some
пример отлично работает
- person chovy; 24.02.2017
"24.7"
и вы хотите соответствовать именно этому, вам нужно избежать этого .
перед передачей строки в new RegExp
, потому что в противном случае это будет токен регулярного выражения .
(здесь любой символ).
- person T.J. Crowder; 24.02.2017
re.test(text)
, и в половине случаев это дает мне ложь, а в другой - правду. Ваш .some
работает нормально.
- person chovy; 25.02.2017
g
и состояния, в котором находится регулярное выражение. Если вы используете test
, вам не нужен флаг g
.
- person T.J. Crowder; 25.02.2017
g
.
- person chovy; 26.02.2017
g
и многострочные строки не имеют ничего общего друг с другом.
- person T.J. Crowder; 26.02.2017
indexOf
(или более новый includes
) в массиве строк, передавая строку для их проверки.
- person T.J. Crowder; 10.08.2020
substrings.some(v => v !== '' && str.includes(v))
- person Freddy Daniel; 19.11.2020
Однострочное решение
substringsArray.some(substring=>yourBigString.includes(substring))
Возвращает true\false
, если подстрока exists\does'nt exist
Требуется поддержка ES6
Для людей, которые ищут в Google,
Твердый ответ должен быть.
const substrings = ['connect', 'ready'];
const str = 'disconnect';
if (substrings.some(v => str === v)) {
// Will only return when the `str` is included in the `substrings`
}
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]
}
}
изменить: если порядок тестов не имеет значения, вы можете использовать это (только с одной переменной цикла):
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]
}
}
len
не требуется, просто отметьте i < arr.length
.
- person GreySage; 26.02.2020
Лучший ответ здесь: он также нечувствителен к регистру
var specsFilter = [.....];
var yourString = "......";
//if found a match
if (specsFilter.some((element) => { return new RegExp(element, "ig").test(yourString) })) {
// do something
}
Если массив невелик, вы можете просто зациклить и проверить строку по каждой подстроке индивидуально, используя indexOf()
. В качестве альтернативы вы можете создать регулярное выражение с подстроками в качестве альтернативы, что может быть или не быть более эффективным.
Функция 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
}
Не то чтобы я предлагаю вам пойти и расширить / изменить прототип String
, но вот что я сделал:
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
Это очень поздно, но я столкнулся с этой проблемой. В моем собственном проекте я использовал следующее, чтобы проверить, находится ли строка в массиве:
["a","b"].includes('a') // true
["a","b"].includes('b') // true
["a","b"].includes('c') // false
Таким образом, вы можете взять предопределенный массив и проверить, содержит ли он строку:
var parameters = ['a','b']
parameters.includes('a') // true
Рисунок из книги T.J. Решение Crowder, я создал прототип для решения этой проблемы:
Array.prototype.check = function (s) {
return this.some((v) => {
return s.indexOf(v) >= 0;
});
};
substringsArray.every(substring=>yourBigString.indexOf(substring) === -1)
За полную поддержку;)
Для полной поддержки (в дополнение к версиям @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)
Используя 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
основываясь на ответе Т.Дж. Краудера
использование экранированного регулярного выражения для проверки наличия "хотя бы один раз" хотя бы одной из подстрок.
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 ...'));
Если вы работаете с длинным списком подстрок, состоящим из полных «слов», разделенных пробелами, или любого другого общего символа, вы можете быть немного умнее в своем поиске.
Сначала разделите вашу строку на группы по X, затем X + 1, затем X + 2, ..., вплоть до Y. X и Y должны быть количеством слов в вашей подстроке с наименьшим и наибольшим количеством слов соответственно. Например, если X равно 1, а Y равно 4, "Альфа-Бета-Гамма-дельта" станет:
«Альфа» «Бета» «Гамма» «Дельта»
«Альфа Бета» «Бета Гамма» «Гамма Дельта»
«Альфа Бета Гамма» «Бета Гамма Дельта»
«Альфа Бета Гамма Дельта»
Если бы X было 2, а Y было бы 3, вы бы опускали первую и последнюю строки.
Теперь вы можете быстро искать в этом списке, если вставляете его в Set (или Map), намного быстрее, чем при сравнении строк.
Обратной стороной является то, что вы не можете искать такие подстроки, как «ta Gamm». Конечно, вы можете учесть это, разбивая по символам, а не по словам, но тогда вам часто придется создавать массивный Set, и время / память, потраченные на это, перевешивают преимущества.
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();
вы можете проверить это и вернуть массив совпадающих слов с помощью фильтра
Проверить можно так:
<!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()))
map()
? Я помню, что читал что-то по этой теме ... - person Martin Hennings   schedule 07.04.2011map
, сколькоsome
.some
поможет, но вам придется передать ему функцию. - person T.J. Crowder   schedule 07.04.2011