Оптимизировать код javascript при поиске совпадений в массиве

В принципе, мне нужно получить слова из массива, которые содержатся в основной строке

У меня есть код цикла, но я думаю, что есть один-лайнер, чтобы сделать трюк. Мне нужен код для оптимизации не только длины кода, но и производительности.

Спасибо

var aValidWords = ["ex", "exes", "expert", 
                   "experts", "expertise", "sex", "sexes", 
                   "exchange", "change", "changes"];
var sMainWord = "expertsExchange";
var aPossibleWords = new Array();

var sMainWordLower = sMainWord.toLowerCase();
for(i=0; i < aValidWords.length; i++){
    var sCurrentWord = aValidWords[i].toLowerCase();
    if(sMainWordLower.indexOf(sCurrentWord) != -1){
        aPossibleWords.push(aValidWords[i]);
    }
}

document.write(aPossibleWords.join("<br />"));

Ответ 1

Я думаю, что ваш код приличный.

Если вас действительно беспокоит производительность, вы можете попробовать какой-то сложный метод, например Boyer-Moore. Но если у вас просто несколько паттернов и относительно короткие строки, тогда накладные расходы на инициализацию выше, чем преимущество, поэтому вы должны придерживаться простого подхода. См. Таблицу сравнения Википедии http://en.wikipedia.org/wiki/String_searching_algorithm#Single_pattern_algorithms

Ответ 2

Я сравнил три возможные реализации:

Альтернатива 1 - Использование для цикла:

function alternative1(aValidWords, sMainWordLower) {
    var aPossibleWords1 = [];
    for(i=0; i < aValidWords.length; i++){
        if(sMainWordLower.indexOf(aValidWords[i]) != -1){
            aPossibleWords1.push(aValidWords[i]);
        }
    }
    return aPossibleWords1;
}

Альтернатива 2 - Использование функции jQuery grep:

function alternative2(aValidWords, sMainWordLower) {
    return $.grep(aValidWords, function(word) {
              return sMainWordLower.indexOf(word) != -1;                    
         }
    )
}

Альтернатива 3. Использование JavaScript native фильтр (IE9, Chrome, Firefox, Opera, Safari):

function alternative3(aValidWords, sMainWordLower) {
    return aValidWords.filter(function(word) {
              return sMainWordLower.indexOf(word) != -1;                    
         }
    )
}

Я измерил время выполнения с помощью инструмента профиля Chrome. Каждая альтернатива была выполнена 10 раз с массивом случайных слов milion. Результаты:

  • Альтернатива 1: 20 исполнений → 21,68s
  • Альтернатива 2: 20 исполнений → 26,31s
  • Альтернатива 3: 20 исполнений → 34,66s

Я был удивлен тем фактом, что эта функция JavaScript Filter была настолько медленной.

Если вы не будете самостоятельно измерять время выполнения, jsFiddle - это займет некоторое время для script закончить.

В целом эти три альтернативы проще всего. Если это время выполнения подходит вам, используйте один из них, иначе ответ @Pumbaa80 будет правильным.

[ОБНОВЛЕНИЕ]

Для объяснения результатов (почему функция JQuery grep быстрее, чем функция встроенного JavaScript-фильтра), обратите внимание на этот вопрос . jsFiddle код также был перенесен на jsPerf благодаря @Alexander.

Ответ 3

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

for(var i=0; i<aValidWords.length; i++) {
    if (new RegExp(aValidWords[i], 'i').test(sMainWord))
        aPossibleWords.push(aValidWords[i]);
}