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

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