JavaScript | Как удалить повторяющиеся последовательности одинаковых символов в строке? — efim360.ru

JavaScript | Как удалить повторяющиеся последовательности одинаковых символов в строке?

 

Пример № 1 - последовательность одинаковых символов встречается один раз в строке

Есть строка:

var stroka = "Магазиииииииииин"

В этой строке очень часто записана буква "и" - одна следом за другой. Как удалить "лишние" буквы "и" и оставить только одну?

Воспользуемся квантификатором "+" и отберём последовательность повторяющихся букв "и"

stroka.match(/и+/)

Нам вернётся такой объект:

["ииииииииии", index: 5, input: "Магазиииииииииин", groups: undefined]

Знак плюс "+" означает сопоставление текущего элемента с предшествующим элементом один или более раз. Эквивалентен квантификатору {1,}

Можем заменить:

var stroka2 = stroka.replaceAll(stroka.match(/и+/), "и")

Получим:

stroka2
"Магазин"

 

Пример № 2 - последовательность одинаковых символов встречается несколько раз в строке

Есть строка:

var stroka = "Маагаааааазин"

Как удалить "лишние" буквы "а" из двух последовательностей и оставить только одну?

var stroka2 = stroka.replace(/а+/g,'а')
или
var stroka2 = stroka.replace(/а+(?=а)/g,'')

Такая команда удалит все дубли букв "а" во всех последовательностях строки.

Удаление через Дизъюнкцию:

Удалили все повторяющиеся последовательности букв а - JavaScript
Удалили все повторяющиеся последовательности букв а - JavaScript

Удаление через Утверждение:

Удалили все повторяющиеся последовательности букв а - через утверждение - JavaScript
Удалили все повторяющиеся последовательности букв а - через утверждение - JavaScript

 

Как это работает?

Конструктор регулярных выражений (RegExp) применяет следующую грамматику к входному шаблону String. Ошибка возникает, если грамматика не может интерпретировать String как расширение Pattern.

В паттерне (Pattern) можно использовать Утверждения (Assertion):

Assertion - RegExp - JavaScript
Assertion - RegExp - JavaScript

В нашем случае мы использовали конструкцию Утверждения ( ? = Disjunction[?U, ?N] )

То есть мы сопоставляем то, что находится слева от круглой скобки с тем, что находится внутри круглых скобок. Дизъюнкция (Disjunction) - это разъединение, разделение. Нашим символом разделения будет являться буква "а". В качестве сопоставления мы указали на букву "а" перед Утверждением (слева от круглой скобки). То есть, мы имеем как-бы две буквы "а". Цветами отмечены для лучшего понимания:

/а+(?=а)/g

Мы добавили квантификатор "+" к сопоставляемой букве "а", чтобы отловить множественные появления последовательностей буквы "а" в строке. Внутри утверждения мы ищем границы, где буква "а" соседствует с такой же буквой "а" (символьное равенство).

Затем мы использовали флаг "g" для регулярных выражений, который говорит нам о том, что условие Утверждения будет проверено "глобально" по всей строке. То есть при помощи флага "g" мы отловим все возможные варианты последовательностей букв с квантификатором "а+". В этом случае флаг "g" выходит за границу регулярного выражения / / и размещается справа.

 

Когда мы отловили все варианты последовательностей буквы "а" (где "а" соседствует с "а") по всей строке, то теперь можем воспользоваться методом замены replace() для объектов-прототипов String. Искомые значения (первый параметр) мы будем заменять на пустую строку (второй параметр). Почему на пустую строку, а не на букву "а". Потому что Утверждение находит только границы между одной последней буквы "а" в последовательности возможных.

Примеры: а|aаа|a, ааа|a, и так далее.

Когда начнётся замена, тогда все вариации (что слева от Границы Утверждения) будут заменены на пустую строку, а значит останется только один символ "а", который по факту является последним в цепочке однотипных последовательностей. Напомню, что сопоставление ведётся по левой стороне Утверждения - слева у нас "а+".

Схема работы метода replace со строкой, регулярным выражением, вкантификатором и Утверждением - JavaScript
Схема работы метода replace со строкой, регулярным выражением, вкантификатором и Утверждением - JavaScript

В этом Утверждении соответствие символов велось по "началу" последовательности букв "а".

Но мы можем решить задачу другой конструкцией регулярных выражений и вести соответствие последовательности по "концу":

var stroka = "Маагаааааазин"
var stroka2 = stroka.replace(/(?<=а)а+/g,'')

 

Удалили все повторяющиеся последовательности букв а - через утверждение по концу - JavaScript
Удалили все повторяющиеся последовательности букв а - через утверждение по концу - JavaScript

 

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

JavaScript | Строки (String)

JavaScript | Флаги регулярных выражений

ECMAScript | Квантификатор (Quantifier) | Регулярные выражения (Regular Expression)

JavaScript | Квантификаторы *(звёздочка), +(плюс), ?(вопрос)

JavaScript | Квантификатор {} фигурные скобки в регулярных выражениях

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

Стандарт ECMAScript - Раздел "22.1.3.17 String.prototype.replace ( searchValue, replaceValue )" - https://tc39.es/ecma262/#sec-string.prototype.replace

Стандарт ECMAScript - Раздел "22.2.2.5.1 RepeatMatcher ( m, min, max, greedy, x, c, parenIndex, parenCount )" - https://tc39.es/ecma262/#sec-runtime-semantics-repeatmatcher-abstract-operation

Стандарт ECMAScript - Раздел "22.2 RegExp (Regular Expression) Objects" - https://tc39.es/ecma262/#sec-regexp-regular-expression-objects