JavaScript | Как найти строку в массиве, по точной словоформе искомого слова на русском языке без учёта регистра? — efim360.ru

JavaScript | Как найти строку в массиве, по точной словоформе искомого слова на русском языке без учёта регистра?

Задача заключается в отборе строк, где искомая словоформа может быть в начале строки, в середине, а также в конце строки (предложения).

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

 

Вводные данные

Представим, что у нас имеется массив из строк, которые являются предложениями или короткими словосочетаниями:

let arr = ['Белый снег', 'Поверхность стола белая, с вкраплениями', 'Немного белый оттенок', 'Местами Белый', 'Окрас белыйсветлый'];

Нашей искомой словоформой будет «белый«.

Слипшиеся слова по факту будут являться другими словоформами. Их мы учитывать не будем. Для них должен работать отдельный инструмент, который будет заниматься поиском синтаксических ошибок в русском языке.

 

Три варианта нахождения словоформы в строке

На первом шаге можно получать массив, в котором все строковые элементы будут в нижнем регистре. Но это не обязательно.

arr.map(i=>i.toLowerCase());

Теперь нужно оформить шаблон регулярного выражения, который будет правильно сопоставлять для нас строки.

Нам достаточно найти одно сопоставление в строке. Нам не нужно перепроверять всю строку от начала и до конца. Нам просто нужен факт существования, а не точное расположение.

 

Вариант № 1 — словоформа находится в самом начале строки

arr.map(i=>i.toLowerCase()).filter(i=>i.match(/^белый[^абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ]+/))

Под это сопоставление подойдёт первый элемент массива:

['белый снег']

 

Вариант № 2 — словоформа находится в середине строки

arr.map(i=>i.toLowerCase()).filter(i=>i.match(/[^абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ]+?белый[^абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ]+/))

Под это сопоставление подойдёт третий элемент массива:

['немного белый оттенок']

 

Вариант № 3 — словоформа находится в конце строки

arr.map(i=>i.toLowerCase()).filter(i=>i.match(/[^абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ]+белый$/))

Под это сопоставление подойдёт четвёртый элемент массива:

['местами белый']

 

Что мы получили?

Из всех пяти элементов массива мы не получили два значения. Это элемент ‘Поверхность стола белая, с вкраплениями‘ и элемент ‘Окрас белыйсветлый‘. Оба этих элемента не включают искомую нами словоформу.

Из всех пяти элементов массива мы получили три строки, которые представляют для нас полезную информацию.

 

Объединение трёх вариантов в один обработчик

Нам нужно упаковать алгоритм нахождения существования словоформы в одну функцию.

Функция будет работать со строкой и словоформой, а возвращать её результат сопоставления в логическом виде — встречается словоформа в строке или нет.

Но мы оформим нашу функцию с учётом особенностей работы метода filter().

 

function word_form_includes(str, index, obj){

    //console.log(str);

    //console.log(index);

    //console.log(obj);

    //console.log(this);

    if(str.toLowerCase() == this.wordform.toLowerCase()){return true}

    let re1, re2, re3; // переменные для объектов регулярных выражений

    re1 = new RegExp(`^${this.wordform.toLowerCase()}[^абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ]+`);

    re2 = new RegExp(`[^абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ]+?${this.wordform.toLowerCase()}[^абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ]+`);

    re3 = new RegExp(`[^абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ]+${this.wordform.toLowerCase()}$`);

 

    let cond1, cond2, cond3; // переменные для результата присутствия словоформы в строке

    cond1 = str.toLowerCase().match(re1);

    cond2 = str.toLowerCase().match(re2);

    cond3 = str.toLowerCase().match(re3);

 

    if(cond1 || cond2 || cond3){return true}; // итоговое сравнение ИЛИ ИЛИ

    return false;

}

 

Внутри функции обработчика мы будем использовать ключевое слово this, чтобы указать на объект контекста вызова данной функции. Привязку this мы получим от объекта, переданного вторым параметром в метод filter().

Объектом контекста вызова функции обработчика будет объект — {wordform:`белый`}.

arr.filter(word_form_includes, {wordform:`белый`})

Результат работы функции обработчика — массив из трёх строк, в которых словоформа была найдена:

['Белый снег', 'Немного белый оттенок', 'Местами Белый']
Отобрали строки в массиве, где встречается нужная нам словоформа на русском языке - JavaScript
Отобрали строки в массиве, где встречается нужная нам словоформа на русском языке — JavaScript

 

Информационные ссылки

Стандарт ECMAScript — Раздел «The RegExp Constructor» — https://tc39.es/ecma262/#sec-regexp-constructor

Стандарт ECMAScript — Раздел «String.prototype.match ( regexp )» — https://tc39.es/ecma262/#sec-string.prototype.match

Стандарт ECMAScript — Раздел «String.prototype.toLowerCase ( )» — https://tc39.es/ecma262/#sec-string.prototype.tolowercase

Стандарт ECMAScript — Раздел «Array.prototype.filter ( callbackfn [ , thisArg ] )» — https://tc39.es/ecma262/#sec-array.prototype.filter

Стандарт ECMAScript — Раздел «Array.prototype.map ( callbackfn [ , thisArg ] )» — https://tc39.es/ecma262/#sec-array.prototype.map

Стандарт ECMAScript — Раздел «Binary Logical Operators» — https://tc39.es/ecma262/#sec-binary-logical-operators