Но так как задача похожа на поиск по БД, то мне захотелось использовать синтаксис поиска MySQL функции like() - она очень удобна, когда не нужно явно применять поиск по сложному регулярному выражению. Например: поиск строк начинающихся, заканчивающихся какой-то подстрокой или включают подстроку (что совпадало с моей задачей).
Плюс ко всему - нужно уметь динамически генерировать это условие. Конечно, в JavaScript легко создать регулярное выражение из строки с помощью конструктора new RegExp(pattern, attrs), но это не так красиво как использование like. Потому я расширил прототип String этим методом. Внутри он таки использует регулярные выражения, но от программиста это скрыто, и пользоваться этим удобно и интуитивно всем кто знает SQL.
Алгоритм еще может оптимизироваться, но уже сейчас он работает довольно быстро.
String.prototype.like = function(s) { if(undefined==s || typeof(s)!='string') return false; function replacer(str, p1, p2) { if(p1=='\\') return p2; if(p2=='%') return p1+'.+'; return p1+'\\w'; } var pattern = "^"+s.replace(/(.|^)([%_])/gm, replacer)+'$'; var re = new RegExp(pattern, 'mg'); if(this.match(re)) return true; return false; };
Пример использования:
var s = "Test string"; console.log( s.like("%ing") ); // True console.log( s.like("%in") ); // False console.log( s.like("%in_") ); // True console.log( s.like("Test%") ); // True console.log( s.like("%str%") ); // True console.log( s.like("%spr%") ); // False console.log( s.like("%s_r%") ); // True
Для того чтобы использовать символы "%", "_" в строке поиска, их нужно экранировать двумя бэк-слешами "\\%".
Не совсем, конечно, хорошо прямо к стандартному объекту String добавлять функцию like. Особенно, когда идет разработка командой. В один прекрасный момент можно будет обнаружить кучу недокументированных возможностей у объекта String :) А сама идея интересная. И не забыть экранировать символы "[", "]" и другие служебные.
ОтветитьУдалитьнехорошо расширять прототип Object, так как тогда надо во всех переборах хешей обязательно проверять .hasOwnProperty() - тоесть отсеивать сторонние ключи которые добавяться при расширении прототипа. А если в проекте команде запрещено расширять прототип Object - проверку можно опустить (хотя согласно правильным подходам программирования она должна всегда быть)
ОтветитьУдалитьРасширение прототипа String никаких ограничений не добавляет, потому вполне удобно так делать. Для предотвращения недокументированных возможностей - прототипы расширяем в одном куске кода и снабжаем комментариями и документацией
Спасибо! Пригодилось.
ОтветитьУдалить