Сопоставление JavaScript с массивом

Я хотел бы знать, как сопоставить строку с массивом регулярных выражений.
Я знаю, как сделать это, перебирая массив в цикле.
Я также знаю, как это сделать, создав длинное регулярное выражение, разделенное символом |
Я надеялся на более эффективный способ, например

if (string contains one of the values in array) {

Например:

string = "the word tree is in this sentence";  
array[0] = "dog";  
array[1] = "cat";  
array[2] = "bird";  
array[3] = "birds can fly";  

В приведенном выше примере условие будет ложным.
Однако string = "She told me birds can fly and I agreed" вернет значение true.


person Xi Vix    schedule 02.06.2011    source источник
comment
Причина, по которой я хотел бы использовать массив вместо | массив может стать большим с сотнями записей   -  person Xi Vix    schedule 03.06.2011
comment
Как насчет предложения «Гусеница…», в ​​котором слово «кошка» входит в состав другого слова?   -  person Gumbo    schedule 03.06.2011
comment
Это нормально... Я могу настроить регулярные выражения с границами слов, если это необходимо.   -  person Xi Vix    schedule 03.06.2011
comment
@xivix: Итак, вы ищете строгие совпадения, верно? Потому что в этом случае есть более эффективный подход.   -  person Gumbo    schedule 03.06.2011
comment
Не уверен, что вы подразумеваете под строгими совпадениями. Пример был упрощен, однако я буду использовать различные функции регулярных выражений для сопоставления различных строк сравнения с входной строкой. Например, если бы я хотел изолировать кошку, я бы использовал \bcat\b   -  person Xi Vix    schedule 03.06.2011
comment
@xivix: я думал, вы пытаетесь сопоставить целые слова.   -  person Gumbo    schedule 03.06.2011
comment
Я не понимаю, как какое-либо решение не должно включать в себя цикл по всему массиву.   -  person Liviu T.    schedule 03.06.2011
comment
Что более эффективно: перебрать массив в цикле или поместить весь массив в одно длинное регулярное выражение, разделенное полосами?   -  person Xi Vix    schedule 03.06.2011


Ответы (4)


Как насчет создания регулярного выражения на лету, когда оно вам нужно (при условии, что массив изменяется с течением времени)

if( (new RegExp( '\\b' + array.join('\\b|\\b') + '\\b') ).test(string) ) {
  alert('match');
}

демонстрация:

string = "the word tree is in this sentence"; 
var array = [];
array[0] = "dog";  
array[1] = "cat";  
array[2] = "bird";  
array[3] = "birds can fly";  

if( (new RegExp( '\\b' + array.join('\\b|\\b') + '\\b') ).test(string) ){
    alert('match');
}
else{
    alert('no match');
}


Для браузеров, поддерживающих JavaScript версии 1.6, вы можете использовать some(). метод

if ( array.some(function(item){return (new RegExp('\\b'+item+'\\b')).test(string);}) ) {
 alert('match');
}

демонстрация:

string = "the word tree is in this sentence"; 
var array = [];
array[0] = "dog";  
array[1] = "tree";  
array[2] = "bird";  
array[3] = "birds can fly";  

if ( array.some(function(i){return (new RegExp('\\b'+i+'\\b')).test(string);}) ) {
 alert('match');
}

person Gabriele Petrioli    schedule 02.06.2011
comment
Ну, это метод бара, о котором я упоминал выше. Я знаю, как настроить длинное регулярное выражение с полосами ... но в конечном итоге оно станет ОЧЕНЬ длинным регулярным выражением, и я надеялся на более элегантное/эффективное решение. Просто интересно, есть ли в Javascript какие-либо встроенные функции, которые решают эту проблему. - person Xi Vix; 03.06.2011
comment
Если нет элегантного способа сделать это, то не лучше ли зациклиться на массиве и запустить простое регулярное выражение x раз? Или поместить все регулярные выражения в одно длинное сложное регулярное выражение? - person Xi Vix; 03.06.2011
comment
Это сработало. Спасибо :) Это кажется более эффективным, чем метод, который я использовал. - person Xi Vix; 03.06.2011
comment
Просто хотел добавить, что мой пакет npm.im/regexr может упростить работу с регулярными выражениями (экранирование не нужно). - person trusktr; 05.04.2016

(Много лет спустя)

Моя версия ответа @Gaby, так как мне нужен был способ проверить происхождение CORS на соответствие регулярным выражениям в массиве:

var corsWhitelist = [/^(?:.+\.)?domain\.com/, /^(?:.+\.)?otherdomain\.com/];

var corsCheck = function(origin, callback) {
  if (corsWhitelist.some(function(item) {
    return (new RegExp(item).test(origin));
  })) {
    callback(null, true);
  } 
  else {
    callback(null, false);
  }
}

corsCheck('otherdomain.com', function(err, result) {
  console.log('CORS match for otherdomain.com: ' + result);  
});

corsCheck('forbiddendomain.com', function(err, result) {
  console.log('CORS match for forbiddendomain.com: ' + result);  
});
person Ville    schedule 07.09.2015

Если у вас есть литеральные строки в массиве с именем strings, который вы хотите сопоставить, вы можете объединить их в чередование, выполнив

new RegExp(strings.map(
    function (x) {  // Escape special characters like '|' and '$'.
      return x.replace(/[^a-zA-Z]/g, "\\$&");
    }).join("|"))

Если у вас есть не только буквальные строки, вы хотите комбинировать регулярные выражения, тогда вы используете http://code.google.com/p/google-code-prettify/source/browse/trunk/js-modules/combinePrefixPatterns.js

/**
 * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
 * matches the union of the sets of strings matched by the input RegExp.
 * Since it matches globally, if the input strings have a start-of-input
 * anchor (/^.../), it is ignored for the purposes of unioning.
 * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
 * @return {RegExp} a global regex.
 */
person Mike Samuel    schedule 02.06.2011

Это нормально ?

function checkForMatch(string,array){
    var arrKeys = array.length;
    var match = false;
    var patt;
    for(i=0; i < arrKeys; i++ ){
        patt=new RegExp(" "+array[i]+" ");
        if(patt.test(string))
           match = true;
    }
    return match;
}

string = "She told me birds can fly and I agreed"; 

var array = new Array();
array[0] = "dog";  
array[1] = "cat";  
array[2] = "bird";  
array[3] = "birds can fly";


alert(checkForMatch(string, array));
person T1000    schedule 02.06.2011
comment
Хорошо, спасибо, но я уже знал, как перебрать массив, что я и делаю сейчас. Я предполагаю, что НЕКОТОРАЯ функция, упомянутая Габи выше, является наиболее близкой к тому, что я ищу. - person Xi Vix; 03.06.2011