Come verificare se una stringa contiene testo da una matrice di sottostringhe in JavaScript?


163

Abbastanza diretto. In javascript, devo verificare se una stringa contiene sottostringhe contenute in un array.


Non c'è una map()funzione nella nuova versione HTML5-JavaScript? Ricordo di aver letto qualcosa sull'argomento ...
Martin Hennings,

@Martin: buon punto, non maptanto some. somesarebbe d'aiuto, ma dovresti passare una funzione.
TJ Crowder,

Risposte:


224

Non c'è niente integrato che lo farà per te, dovrai scrivere una funzione per esso.

Se sai che le stringhe non contengono nessuno dei caratteri speciali nelle espressioni regolari, puoi barare un po ', in questo modo:

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

... che crea un'espressione regolare che è una serie di alternanze per le sottostringhe che stai cercando (ad es. one|two) e fa dei test per vedere se ci sono corrispondenze per ognuna di esse, ma se una delle sottostringhe contiene caratteri speciali in espressioni regolari ( *, [, ecc), che avrebbe dovuto sfuggire loro prima ed è meglio solo facendo il ciclo noioso, invece.

Esempio live:


In un commento sulla domanda, Martin chiede del nuovo Array.prototype.mapmetodo in ECMAScript5. mapnon è di grande aiuto, ma someè:

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

Esempio live:

Lo hai solo su implementazioni conformi a ECMAScript5, anche se è banale il polyfill.


Aggiornamento nel 2020 : l' someesempio può essere più semplice con una funzione freccia (ES2015 +) e potresti usare includesinvece di indexOf:

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

Esempio live:

O anche lanciarlo bind, anche se per me la funzione freccia è molto più leggibile:

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

Esempio live:


2
"Intendiamoci, significa un po 'di spese generali ..." ma niente di cui preoccuparsi .
TJ Crowder,

È possibile estendere sopra soluzione, eliminando tutti i caratteri regex tranne il '|': new RegExp(substrings.join("|").replace(/[^\w\s^|]/gi, '')).test(string).
user007

l'uso di indexOf può essere troppo sfocato e produrre un risultato strano. Può essere semplicemente messo per abbinare la stringa usando l'operatore di uguale. ad es. ('disconnect'.indexOf('connect') >= 0) === truema('disconnect' === 'conenct') === false
kylewelsby il

@halfcube: Huh? Non ti capisco, ho paura. Nulla nella risposta sopra suggerisce che 'disconnect' === 'connect'sarà tutt'altro false. Inoltre, indexOfnon è sfocato, è molto chiaramente definito.
TJ Crowder,

indexOfcorrisponderà a entrambi disconnecte connectdove in un caso che ho sperimentato, questi sono due casi diversi per cui voglio restituire risultati in un condizionale.
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
   }
}

50

Una soluzione di linea

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

Restituisce true\falsese sottostringaexists\does'nt exist

Richiede supporto ES6


Ottima soluzione usando le funzioni freccia
GuerillaRadio

7
Ragazzi ... quando ero un bambino dovevamo usare queste cose chiamate loop "for" e dovevi usare più linee e sapere se il tuo array era basato su 1 o zero, sì ... metà del tempo che hai è sbagliato e ho dovuto eseguire il debug e cercare un piccolo bugger chiamato "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
il più semplice da capire!
Daryl H,

Inoltre restituisce la prima occorrenza della parola nella stringa, il che è molto utile. Non solo un vero / falso.
Kai Noack,

20

Per le persone che cercano su Google,

La risposta solida dovrebbe essere.

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
o più corto: if (substrings.some (v => v === str)) {
kofifus

10
Si noti che questa è una risposta a una domanda leggermente diversa, che chiede se una stringa contiene testo da una matrice di sottostringhe. Questo codice controlla se una stringa è una delle sottostringhe. Dipende da cosa si intende per "contiene" suppongo.
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]
    }
}

modifica: se l'ordine dei test non ha importanza, puoi usarlo (con una sola variabile di ciclo):

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

Il tuo primo esempio non ha bisogno della lenvariabile, basta controllare i < arr.length.
GreySage,

3

Se l'array non è di grandi dimensioni, è possibile semplicemente eseguire il ciclo e controllare la stringa su ogni sottostringa singolarmente utilizzando indexOf(). In alternativa puoi costruire un'espressione regolare con sottostringhe come alternative, che potrebbero essere o meno più efficienti.


Diciamo che abbiamo un elenco di 100 sottostringhe. In che modo sarebbe più efficiente: RegExp o loop?
Diyorbek Sadullayev il

3

Funzione Javascript per cercare una matrice di tag o parole chiave usando una stringa di ricerca o una matrice di stringhe di ricerca. (Utilizza ES5 alcuni metodi array e funzioni freccia 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;
}

Esempio di utilizzo:

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

2

Non che sto suggerendo di andare ed estendere / modificare Stringil prototipo, ma questo è quello che ho fatto:

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

Attingendo alla soluzione di TJ Crowder, ho creato un prototipo per affrontare questo problema:

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

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

Per il pieno supporto;)


2

La migliore risposta è qui: anche questo non fa distinzione tra maiuscole e minuscole

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

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

1

Utilizzando underscore.js o lodash.js, puoi eseguire le seguenti operazioni su una matrice di stringhe:

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 su una singola stringa:

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

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

// true

1

È molto tardi, ma ho riscontrato questo problema. Nel mio progetto ho usato quanto segue per verificare se una stringa era in un array:

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

In questo modo è possibile prendere un array predefinito e verificare se contiene una stringa:

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

1

basandosi sulla risposta di TJ Crowder

utilizzando RegExp con escape per verificare l'occorrenza "almeno una volta" di almeno una delle sottostringhe.

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

Se stai lavorando con un lungo elenco di sottostringhe costituite da "parole" complete separate da spazi o da qualsiasi altro carattere comune, puoi essere un po 'intelligente nella tua ricerca.

Dividi prima la stringa in gruppi di X, quindi X + 1, quindi X + 2, ..., fino a Y. X e Y dovrebbero essere il numero di parole nella sottostringa con il minor numero e il maggior numero di parole rispettivamente. Ad esempio se X è 1 e Y è 4, "Alpha Beta Gamma Delta" diventa:

"Alpha" "Beta" "Gamma" "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, ometteresti la prima e l'ultima riga.

Ora puoi cercare rapidamente questo elenco se lo inserisci in un set (o in una mappa), molto più velocemente rispetto al confronto delle stringhe.

Il rovescio della medaglia è che non è possibile cercare sottostringhe come "ta Gamm". Ovviamente potresti permetterlo dividendo per carattere invece che per parola, ma spesso avresti bisogno di costruire un set enorme e il tempo / la memoria speso per farlo supera i benefici.


1

Per il supporto completo (in aggiunta 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)


0

Puoi controllare in questo modo:

<!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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.