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

163

Całkiem proste. W javascript muszę sprawdzić, czy ciąg zawiera jakiekolwiek podciągi przechowywane w tablicy.

PercivalMcGullicuddy
źródło
Czy nie ma map()funkcji w nowej wersji HTML5-JavaScript? Pamiętam, że czytałem coś na ten temat ...
Martin Hennings,
@Martin: Słuszna uwaga, nie maptyle some. somepomogłoby, ale musiałbyś przekazać mu funkcję.
TJ Crowder

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:

TJ Crowder
źródło
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
   }
}
raveren
źródło
50

Rozwiązanie jednoprzewodowe

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

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

Potrzebuje obsługi ES6

Praveena
źródło
Ś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);
Jim Blackler
źródło
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`
}
kylewelsby
źródło
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]
    }
}
użytkownik
źródło
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.

Gintautas Miliauskas
źródło
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
}
David Douglas
źródło
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

akinuri
źródło
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;
  });
};
alavry
źródło
2
substringsArray.every(substring=>yourBigString.indexOf(substring) === -1)

Za pełne wsparcie;)

ricca
źródło
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
    }
Adel Mourad
źródło
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
BuffMcBigHuge
źródło
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
Lincoln Anders
źródło
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 ...'));

DhavalW
źródło
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.

Emil Norén
źródło
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)

TitanFighter
źródło
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>
Dhaval Soni
źródło
-1
let obj = [{name : 'amit'},{name : 'arti'},{name : 'sumit'}];
let input = 'it';

Użyj filtra:

obj.filter((n)=> n.name.trim().toLowerCase().includes(input.trim().toLowerCase()))
ArtiSK
źródło
odwiedź stronę i sprawdź, jak odpowiedzieć na pytanie .
Yunus Temurlenk
@YunusTemurlenk thnx
ArtiSK