Страницы

Поиск по вопросам

пятница, 27 декабря 2019 г.

Как удалить повторяющиеся буквы из слова с помощью регулярных выражений?

#регулярные_выражения #строки


Подскажите, возможно ли с помощью регулярных выражений удалить из строки повторяющиеся
буквы?

Т.е из строки "aabcdbpep" сделать "cde"
    


Ответы

Ответ 1



Если библиотека регулярных выражений поддерживает блок предварительного просмотра назад любой длины (как в .NET, PyPi regex в Python, JavaScript ECMAScript2018+ (например, в браузере Chrome, в версиях Visual Studio Code после 1.31.0)), это можно сделать одним регулярным выражением в методе замены (sub/replace): (.)(?=.*\1)|(.)(?<=\2.*.) Чтобы точка искала символы перевода строки, не забудьте соответствующий модификатор, например s, re.DOTALL и т.п. Это не самый эффективный способ, так как при поиске активно используется backtracking! Подробности (.)(?=.*\1) - любой символ (захваченный в подмаску №1), после которого есть 0 и более любых символов, а затем тот же символ, который был захвачен первой подмаской | - или (.)(?<=\2.*.) - любой символ (захваченный в подмаску №2), перед которым есть тот же символ, который был захвачен второй подмаской, на расстоянии в 0 и более любых символов. Последняя точка в блоке просмотра назад необходима, так как блок стоит сразу после проверяемого символа (проверяемый шаблон надо повторить). Пример на JavaScript (Chrome): console.log("aabcdbpep".replace(/(.)(?=.*\1)|(.)(?<=\2.*.)/gs, '')) Python (pip install regex): import regex print( regex.sub(r'(.)(?=.*\1)|(.)(?<=\2.*.)', '', "aabcdbpep", flags=regex.I|regex.S) ) C#: Console.WriteLine( Regex.Replace("aabcdbpep", @"(.)(?=.*\1)|(.)(?<=\2.*.)", "", RegexOptions.IgnoreCase|RegexOptions.Singleline) ); В общем случае не следует одной регуляркой удалять все неуникальные символы в строке. Удалить все неуникальные символы можно с помощью простых методов, которые предоставляет вам каждый язык программирования, которые удаляют все те символы строки, количество которых больше одного или позиция первого их вхождения равна позиции последнего. Приведу примерные решения для некоторых "популярных" языков программирования. JavaScript: var s = 'aabcdbpep'; var res = s.split('').filter(function(val, i, str) { return str.lastIndexOf(val) === str.indexOf(val); }).join(""); console.log(res); Python: s = 'aabcdbpep'; res = ''.join([x for x in s if s.count(x) == 1]) C#: var s = "aabcdbpep"; var res = new String(s.Where(x => s.LastIndexOf(x) == s.IndexOf(x)).ToArray()); Ruby s = 'aabcdbpep' res = s.chars.select {|x| s.count(x) == 1}.join # или res = s.chars.select {|x| s.index(x) == s.rindex(x)}.join PHP: $s = 'aabcdbpep'; if (preg_match_all('~\X~u', $s, $chararr)) { echo implode("", array_filter($chararr[0], function ($x) use ($s) { return substr_count($s, $x) === 1; })); } Java: import java.util.stream.*; ... String s = "aabcdbpep"; String res = Arrays.asList(s.split("")) .stream() .filter(x -> s.indexOf(x) == s.lastIndexOf(x)) .collect(Collectors.joining()); В общем, алгоритм может быть таким: Разбить строку на массив (список) символов Удалить повторяющиеся Собрать строку заново. См. Удаление повторяющихся элементов на сайте rosettacode.org.

Ответ 2



для Sublime Text Ищем (.)((.*)(\1))++ заменяем на $3 есть небольшой нюанс - если части между повторами пересекаются между собой (например "12C34E56C78E" эти части: "C34E56C" и "E56C78E"пересекаются) операцию замены нужно повторить

Комментариев нет:

Отправить комментарий