Como verificar se uma string contém texto de uma matriz de substrings em JavaScript?

163

Bem direto. Em javascript, preciso verificar se uma string contém substrings mantidos em uma matriz.

PercivalMcGullicuddy
fonte
Não existe uma map()função na nova versão HTML5-JavaScript? Lembro-me de ter lido algo sobre o assunto ...
Martin Hennings
@ Martin: Bom ponto, nem maptanto some. someajudaria, mas você teria que passar uma função.
TJ Crowder

Respostas:

224

Não há nada embutido que faça isso por você, você terá que escrever uma função para ele.

Se você sabe que as strings não contêm nenhum caractere especial em expressões regulares, você pode trapacear um pouco, assim:

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

... que cria uma expressão regular que é uma série de alternâncias para as substrings que você está procurando (por exemplo, one|two) e testa para verificar se há correspondências para alguma delas, mas se alguma das substrings contém caracteres especiais em regexes ( *,[ etc.), você teria que escapar delas primeiro e é melhor fazer o ciclo chato.

Exemplo ao vivo:


Em um comentário sobre a pergunta, Martin pergunta sobre o novo Array.prototype.mapmétodo no ECMAScript5. mapnão é muita ajuda, mas someé:

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

Exemplo ao vivo:

Você só o possui em implementações compatíveis com ECMAScript5, embora seja trivial o polyfill.


Atualização em 2020 : o someexemplo pode ser mais simples com uma função de seta (ES2015 +) e você pode usar, em includesvez de indexOf:

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

Exemplo ao vivo:

Ou até jogá bind-lo, embora para mim a função de seta seja muito mais legível:

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

Exemplo ao vivo:

TJ Crowder
fonte
2
"Lembre-se, isso significa alguma sobrecarga ..." mas nada para se preocupar .
TJ Crowder
Você pode estender acima solução, removendo todos os caracteres regex exceto o '|': new RegExp(substrings.join("|").replace(/[^\w\s^|]/gi, '')).test(string).
User007
o uso de indexOf pode ser muito confuso e gerar um resultado estranho. Ele pode ser simplesmente colocado para corresponder à string usando o operador igual. Por exemplo, ('disconnect'.indexOf('connect') >= 0) === truemas('disconnect' === 'conenct') === false
kylewels por
@halfcube: Hein? Não estou entendendo você, estou com medo. Nada na resposta acima sugere que 'disconnect' === 'connect'será tudo menos false. Além disso, indexOfnão é confuso, é muito claramente definido.
TJ Crowder
indexOfcorresponderá a ambos disconnecte connectonde, em um caso que eu experimentei, são dois casos diferentes para os quais eu quero retornar resultados condicionais
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
   }
}
Raveren
fonte
50

Solução de uma linha

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

Retorna true\falsese substringexists\does'nt exist

Precisa de suporte do ES6

Praveena
fonte
Ótima solução usando funções de seta
GuerillaRadio
7
Vocês, crianças ... quando eu era criança, tivemos que usar essas coisas chamadas 'for' loops, e você teve que usar várias linhas e saber se sua matriz era baseada em 1 ou zero, sim ... metade do tempo que você tinha errado e teve que depurar e procurar um pequeno bugger chamado 'i'.
precisa saber é
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);
Jim Blackler
fonte
1
mais fácil de entender!
Daryl H
Além disso, ele retorna a primeira ocorrência da palavra na string, o que é muito útil. Não é apenas um verdadeiro / falso.
Kai Noack
20

Para as pessoas pesquisando no Google,

A resposta sólida deve ser.

const substrings = ['connect', 'ready'];
const str = 'disconnect';
if (substrings.some(v => str === v)) {
   // Will only return when the `str` is included in the `substrings`
}
kylewelsby
fonte
2
ou menor: if (substrings.some (v => v === str)) {
kofifus 13/09
10
Observe que essa é uma resposta para uma pergunta um pouco diferente, que pergunta se uma string contém texto de uma matriz de substrings. Este código verifica se uma string é uma das substrings. Depende do que se entende por "contém", suponho.
fcrick 29/05
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]
    }
}

edit: Se a ordem dos testes não importa, você pode usá-lo (com apenas uma variável de loop):

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]
    }
}
do utilizador
fonte
Seu primeiro exemplo não precisa da lenvariável, basta verificar i < arr.length.
GreySage 26/02
3

Se a matriz não for grande, você pode simplesmente fazer um loop e verificar a string em cada substring individualmente usando indexOf(). Como alternativa, você pode construir uma expressão regular com substrings como alternativas, que podem ou não ser mais eficientes.

Gintautas Miliauskas
fonte
Digamos que temos uma lista de 100 substrings. Qual caminho seria mais eficiente: RegExp ou loop?
Diyorbek Sadullayev 27/06
3

Função Javascript para pesquisar uma matriz de tags ou palavras-chave usando uma string de pesquisa ou uma matriz de strings de pesquisa. (Usa ES5 algum método de matriz e funções de seta 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;
}

Exemplo de uso:

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

Não que eu esteja sugerindo que você amplie / modifique Stringo protótipo, mas foi o que eu fiz:

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

akinuri
fonte
2

Partindo da solução de TJ Crowder, criei um protótipo para lidar com esse problema:

Array.prototype.check = function (s) {
  return this.some((v) => {
    return s.indexOf(v) >= 0;
  });
};
alavry
fonte
2
substringsArray.every(substring=>yourBigString.indexOf(substring) === -1)

Para suporte total;)

ricca
fonte
2

A melhor resposta está aqui: Isso também não diferencia maiúsculas de minúsculas

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

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

Usando underscore.js ou lodash.js, você pode fazer o seguinte em uma matriz de cadeias de caracteres:

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

E em uma única sequência:

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

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

// true
BuffMcBigHuge
fonte
1

É tarde demais, mas acabei de encontrar este problema. No meu próprio projeto, usei o seguinte para verificar se uma string estava em uma matriz:

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

Dessa forma, você pode pegar uma matriz predefinida e verificar se ela contém uma sequência:

var parameters = ['a','b']
parameters.includes('a')    // true
Lincoln Anders
fonte
1

com base na resposta de TJ Crowder

usando RegExp com escape para testar a ocorrência "pelo menos uma vez", de pelo menos uma das substrings.

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

DhavalW
fonte
1

Se você estiver trabalhando com uma longa lista de substrings que consistem em "palavras" completas separadas por espaços ou qualquer outro caractere comum, você pode ser um pouco inteligente em sua pesquisa.

Primeiro divida sua string em grupos de X, depois X + 1, depois X + 2, ..., até Y. X e Y devem ser o número de palavras na sua substring com o menor número e a maior quantidade de palavras, respectivamente. Por exemplo, se X é 1 e Y é 4, "Alpha Beta Gamma Delta" se torna:

"Alfa" "Beta" "Gama" "Delta"

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

"Alpha Beta Gamma" "Beta Gamma Delta"

"Alpha Beta Gamma Delta"

Se X fosse 2 e Y fosse 3, você omitiria a primeira e a última linha.

Agora você pode pesquisar nessa lista rapidamente se inseri-la em um conjunto (ou mapa), muito mais rapidamente do que na comparação de cadeias.

A desvantagem é que você não pode procurar por substrings como "ta Gamm". É claro que você poderia permitir isso dividindo por caractere em vez de por palavra, mas muitas vezes precisaria criar um conjunto enorme e o tempo / memória gasto superando os benefícios.

Emil Norén
fonte
1

Para suporte completo (adicionalmente a @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)

TitanFighter
fonte
0

Você pode verificar assim:

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

Use filtro:

obj.filter((n)=> n.name.trim().toLowerCase().includes(input.trim().toLowerCase()))
ArtiSK
fonte
visite e verifique como responder a uma pergunta .
Yunus Temurlenk
@YunusTemurlenk thnx
ArtiSK