Jak sprawdzić, czy ciąg zawiera tekst z tablicy podciągów w JavaScript?


Odpowiedzi:


222

Nie ma nic wbudowanego, co zrobi to za Ciebie, będziesz musiał napisać dla niego funkcję.

Jeśli wiesz, że ciągi znaków nie zawierają żadnych znaków specjalnych w wyrażeniach regularnych, możesz trochę oszukać, na przykład:

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

... które tworzy wyrażenie regularne, które jest serią naprzemiennych podciągów, których szukasz (np. one|two) i sprawdza, czy są dopasowania dla któregokolwiek z nich, ale czy którykolwiek z podciągów zawiera znaki, które są specjalne (w regexes *, [itp), trzeba je najpierw do ucieczki, a ty lepiej po prostu robi pętlę zamiast nudnego.

Przykład na żywo:


W komentarzu do pytania Martin pyta o nową Array.prototype.mapmetodę w ECMAScript5. mapnie jest to bardzo pomocne, ale somejest:

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

Przykład na żywo:

Masz go tylko w implementacjach zgodnych z ECMAScript5, chociaż jest to trywialne w przypadku polyfill.


Aktualizacja w 2020 r . : somePrzykład może być prostszy dzięki funkcji strzałki (ES2015 +) i można użyć includeszamiast indexOf:

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

Przykład na żywo:

Albo nawet bindw to rzucić , chociaż dla mnie funkcja strzałek jest dużo bardziej czytelna:

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

Przykład na żywo:


2
„Pamiętaj, to oznacza trochę narzutów…”, ale nie ma się czym przejmować .
TJ Crowder

Można przedłużyć powyżej rozwiązania, usuwając wszystkie znaki regex wyjątkiem „|”: new RegExp(substrings.join("|").replace(/[^\w\s^|]/gi, '')).test(string).
user007

użycie indexOf może być zbyt rozmyte i dać dziwny wynik. Można go po prostu dopasować do ciągu za pomocą operatora równości. np. ('disconnect'.indexOf('connect') >= 0) === trueale('disconnect' === 'conenct') === false
kylewelsby

@halfcube: Hę? Nie rozumiem cię, obawiam się. Nic w powyższej odpowiedzi nie sugeruje, że 'disconnect' === 'connect'będzie to wszystko inne false. Nie indexOfjest też rozmyty, jest rzeczywiście bardzo jasno zdefiniowany.
TJ Crowder

indexOfdopasuje oba disconnecti connectgdzie w przypadku, którego doświadczyłem, są to dwa różne przypadki, dla których chcę zwrócić wyniki w postaci warunkowej.
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

Rozwiązanie jednoprzewodowe

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

Zwraca true\falsejeśli podciągexists\does'nt exist

Potrzebuje obsługi ES6


Świetne rozwiązanie wykorzystujące funkcje strzałkowe
GuerillaRadio

7
Wy dzieciaki ... kiedy byłem dzieckiem, musieliśmy używać tych rzeczy zwanych pętlami `` for '' i musieliście używać wielu linii i wiedzieć, czy wasza tablica opierała się na 1 czy zero, tak ... o połowę krócej było źle i musiałem debugować i uważać na mały błąd o nazwie „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
najłatwiejszy do zrozumienia!
Daryl H

Dodatkowo zwraca pierwsze wystąpienie słowa w ciągu, co jest bardzo pomocne. Nie tylko prawda / fałsz.
Kai Noack

20

Dla osób szukających w Google,

Solidna odpowiedź powinna brzmieć.

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
lub krócej: if (substrings.some (v => v === str)) {
kofifus

10
Zauważ, że jest to odpowiedź na nieco inne pytanie, które dotyczy pytania, czy ciąg zawiera tekst z tablicy podciągów. Ten kod sprawdza, czy ciąg jest jednym z podciągów. Przypuszczam, że zależy od tego, co rozumie się przez „zawiera”.
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]
    }
}

edycja: Jeśli kolejność testów nie ma znaczenia, możesz użyć tego (tylko z jedną zmienną pętli):

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

Twój pierwszy przykład nie potrzebuje lenzmiennej, po prostu sprawdź i < arr.length.
GreySage

3

Jeśli tablica nie jest duża, możesz po prostu zapętlić i sprawdzić ciąg z każdym podciągiem indywidualnie, używając indexOf(). Alternatywnie możesz skonstruować wyrażenie regularne z podciągami jako alternatywami, które mogą być bardziej wydajne lub nie.


Powiedzmy, że mamy listę 100 podciągów. Który sposób byłby bardziej wydajny: RegExp czy pętla?
Diyorbek Sadullayev

3

Funkcja JavaScript do przeszukiwania tablicy tagów lub słów kluczowych za pomocą ciągu wyszukiwania lub tablicy ciągów wyszukiwania. (Używa ES5 jakiś sposób tablicy i ES6 strzałka funkcje )

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

Przykładowe użycie:

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

2

Nie to, żebym sugerował, abyś poszedł i rozszerzył / zmodyfikował Stringprototyp, ale oto co zrobiłem:

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

Czerpiąc z rozwiązania TJ Crowdera, stworzyłem prototyp, aby poradzić sobie z tym problemem:

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

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

Za pełne wsparcie;)


2

Najlepsza odpowiedź brzmi: tutaj również nie jest rozróżniana wielkość liter

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

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

1

Używając znaku podkreślenia.js lub lodash.js, możesz wykonać następujące czynności na tablicy ciągów:

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

I na jednym sznurku:

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

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

// true

1

Jest już bardzo późno, ale właśnie napotkałem ten problem. W moim własnym projekcie użyłem poniższego, aby sprawdzić, czy ciąg znajduje się w tablicy:

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

W ten sposób możesz wziąć predefiniowaną tablicę i sprawdzić, czy zawiera ciąg:

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

1

opierając się na odpowiedzi TJ Crowdera

używanie wyrażenia Escaped RegExp do testowania wystąpienia „co najmniej raz” co najmniej jednego z podciągów.

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

Jeśli pracujesz z długą listą podciągów składającą się z pełnych „słów” oddzielonych spacjami lub innymi popularnymi znakami, możesz być trochę sprytny w wyszukiwaniu.

Najpierw podziel ciąg na grupy X, potem X + 1, potem X + 2, ..., aż do Y. X i Y powinny być liczbą słów w podłańcuchu zawierającą odpowiednio najmniej i najwięcej słów. Na przykład jeśli X wynosi 1, a Y wynosi 4, „Alpha Beta Gamma Delta” zmienia się na:

„Alfa” „Beta” „Gamma” „Delta”

„Alpha Beta” „Beta Gamma” „Gamma Delta”

„Alpha Beta Gamma” „Beta Gamma Delta”

„Alpha Beta Gamma Delta”

Jeśli X będzie równe 2, a Y będzie 3, pominiesz pierwszy i ostatni wiersz.

Teraz możesz szybko przeszukiwać tę listę, jeśli wstawisz ją do zestawu (lub mapy), znacznie szybciej niż przez porównanie ciągów.

Wadą jest to, że nie możesz wyszukiwać podciągów, takich jak „ta Gamm”. Oczywiście możesz na to pozwolić, dzieląc się według znaków zamiast słów, ale wtedy często musiałbyś zbudować ogromny zestaw, a czas / pamięć spędzona na tym przeważają nad korzyściami.


1

Dla pełnego wsparcia (dodatkowo @ricca „s wersjach programu ).

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

Możesz sprawdzić w ten sposób:

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.