Поиск строки методом like (аналог like из MySQL)

Недавно, мне понадобилось осуществлять поиск по массиву объектов(со строковыми полями). В JavaScript, сложный поиск осуществляется с помощью регулярных выражений, для того чтобы искать в контексте объекта String, есть метод(прототип) match().

Но так как задача похожа на поиск по БД, то мне захотелось использовать синтаксис поиска 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


Для того чтобы использовать символы "%", "_" в строке поиска, их нужно экранировать двумя бэк-слешами "\\%".
Теги:
Поиск строки, like
Добавлено: 13 Апреля 2018 23:18:07 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...