Bir dizenin JavaScript'te bir alt dizgi dizisinden metin içerip içermediğini nasıl kontrol edebilirim?


163

Oldukça düz ileri. Javascript, bir dize bir dizi tutulan alt dizeleri içerip içermediğini denetlemem gerekir.


map()Yeni HTML5-JavaScript sürümünde bir işlev yok mu? Bu konuda bir şeyler okuduğumu hatırlıyorum ...
Martin Hennings

@Martin: İyi bir nokta, mapo kadar da değil some. someyardımcı olur, ancak ona bir işlev iletmeniz gerekir.
TJ Crowder

Yanıtlar:


225

Bunu sizin için yapacak hiçbir şey yoktur, bunun için bir işlev yazmanız gerekir.

Eğer varsa bilmek dizeleri normal ifadelerde özel olan karakterlerden herhangi içermez, o zaman böyle biraz, hile:

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

... bir dizi alternatif olan düzenli bir ifade yaratır. aradığınız alt dizeler için (örn. one|two) ve bunlardan herhangi biri için eşleşme olup olmadığını test eder, ancak alt dizelerden herhangi biri özel olan herhangi bir karakter içeriyorsa normal ifadelerde ( *, [vb.), önce onlardan kaçmanız gerekir ve bunun yerine sıkıcı döngüyü yapmak daha iyi olur.

Canlı Örnek:


Soruya yapılan bir yorumda MartinArray.prototype.map , ECMAScript5'teki yeni yöntemi soruyor . mapo kadar yardımcı değil, amasome :

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

Canlı Örnek:

Çoklu doldurma için önemsiz olsa da, yalnızca ECMAScript5 uyumlu uygulamalarda vardır.


2020'de güncelleme : someÖrnek bir ok işlevi (ES2015 +) ile daha basit olabilir ve aşağıdakiler includesyerine kullanabilirsiniz indexOf:

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

Canlı Örnek:

Ya da bindbenim için ok işlevi çok daha okunabilir olsa da, ona atmak bile :

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

Canlı Örnek:


2
"Dikkat edin, bu biraz havai anlamına geliyor ..." ama umursamayacak bir şey yok .
TJ Crowder

'|' Sen hariç tüm regex karakterleri kaldırarak çözümü yukarıda uzatabilirsiniz: new RegExp(substrings.join("|").replace(/[^\w\s^|]/gi, '')).test(string).
user007

indexOf kullanımı çok bulanık olabilir ve garip bir sonuç verebilir. Eşittir operatörünü kullanarak dizeyi eşleştirmek için basitçe konabilir. eg ('disconnect'.indexOf('connect') >= 0) === truebut('disconnect' === 'conenct') === false
kylewelsby

@halfcube: Ha? Seni anlamıyorum, korkarım. Yukarıdaki cevapta yer alan 'disconnect' === 'connect'hiçbir şey bunun dışında bir şey olduğunu göstermez false. Ayrıca, indexOfbulanık değil, gerçekten çok açık bir şekilde tanımlanmış.
TJ Crowder

indexOfher ikisiyle de eşleşecek disconnectve connectyaşadığım bir durumda, bunlar koşullu olarak sonuç döndürmek istediğim iki farklı durum.
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

Tek hat çözümü

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

Alt true\falsedize olursa dönerexists\does'nt exist

ES6 desteği gerekiyor


Ok fonksiyonlarını kullanarak mükemmel çözüm
GuerillaRadio

7
Siz çocuklar ... geri döndüğümde 'for' döngüleri olarak adlandırdığımız şeyleri kullanmak zorundaydık ve birden fazla satır kullanmak ve dizinizin 1 mi sıfır mı olduğunu bilmek zorundaydınız, evet ... yanlış ve hata ayıklamak ve 'i' adlı küçük bir hata için dışarı bakmak zorunda kaldı.
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
anlaması en kolay olanı!
Daryl H

Ayrıca, dizedeki sözcüğün ilk oluşumunu döndürür, bu da çok yararlıdır. Sadece doğru / yanlış değil.
Kai Noack

20

Google çalışanları için,

Sağlam cevap olmalı.

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
veya daha kısa: if (substrings.some (v => v === str)) {
kofifus

10
Bunun, bir dizenin bir alt dizgi dizisinden metin içerip içermediğini soran biraz farklı bir sorunun cevabı olduğunu unutmayın . Bu kod denetler bir dize eğer olduğunu alt dizilerden birini. Sanırım "içerir" ile ne kastedildiğine bağlıdır.
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]
    }
}

edit: Testlerin sırası önemli değilse, bunu kullanabilirsiniz (sadece bir döngü değişkeni ile):

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

İlk örneğinizin lendeğişkene ihtiyacı yoktur , sadece kontrol edin i < arr.length.
GreySage

3

Dizi büyük değilse, dizeyi ayrı ayrı kullanarak her bir alt dizeye karşı döngü ve kontrol edebilirsiniz indexOf(). Alternatif olarak, alternatif olarak alt dizelerle normal bir ifade oluşturabilirsiniz, bu daha verimli olabilir veya olmayabilir.


Diyelim ki 100 alt dizeden oluşan bir listemiz var. Hangi yol daha verimli olurdu: RegExp veya döngü?
Diyorbek Sadullayev

3

Bir arama dizesi veya bir arama dizesi dizisi kullanarak bir etiket veya anahtar kelime dizisini aramak için Javascript işlevi. ( ES5 bazı dizi yöntemlerini ve ES6 ok işlevlerini kullanır )

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

Örnek kullanım:

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

2

Gitmenizi ve Stringprototipini genişletmenizi / değiştirmenizi önermiyorum, ama yaptığım şey bu:

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

TJ Crowder'ın çözümünden yola çıkarak, bu sorunla başa çıkmak için bir prototip oluşturdum:

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

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

Tam destek için;)


2

En iyi cevap burada: Bu da büyük / küçük harfe duyarlı değil

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

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

1

Underscore.js veya lodash.js kullanarak, bir dizi dizede aşağıdakileri yapabilirsiniz:

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

Ve tek bir dizgide:

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

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

// true

1

Bu çok geç, ama ben sadece bu problemle karşılaştım. Kendi projemde bir dizede bir dizenin olup olmadığını kontrol etmek için aşağıdakileri kullandım:

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

Bu şekilde önceden tanımlanmış bir dizi alıp bir dize içerip içermediğini kontrol edebilirsiniz:

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

1

TJ Crowder'ın cevabı üzerine inşa

alt dizelerden en az birinin "en az bir kez" oluşumunu test etmek için çıkış RegExp kullanarak.

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

Boşluklarla veya başka bir ortak karakterle ayrılmış tam "kelimeler" den oluşan uzun bir alt dize listesiyle çalışıyorsanız, aramanızda biraz zeki olabilirsiniz.

İlk önce dizenizi X, sonra X + 1, sonra X + 2, ..., Y'ye kadar bölün. X ve Y, alt dizenizdeki sırasıyla en az ve en çok kelime içeren kelime sayısı olmalıdır. Örneğin, X 1 ve Y 4 ise, "Alfa Beta Gama Deltası":

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

"Alfa Beta" "Beta Gama" "Gama Deltası"

"Alfa Beta Gama" "Beta Gama Deltası"

"Alfa Beta Gama Deltası"

X 2 ve Y 3 olursa, ilk ve son satırı atlarsınız.

Artık bir Sete (veya Haritaya) dize karşılaştırmasına göre çok daha hızlı eklerseniz bu listede hızlı bir şekilde arama yapabilirsiniz.

Dezavantajı "ta Gamm" gibi alt dizeleri arayamamanızdır. Tabii ki, kelime yerine karaktere bölünerek buna izin verebilirsiniz, ancak daha sonra büyük bir Set oluşturmanız gerekir ve bunu yapmak için harcanan zaman / bellek faydalardan ağır basar.


1

Tam destek için (ek için @ricca sitesindeki 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

Bunu şöyle kontrol edebilirsiniz:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.