Шаг 84.
Однострочники Python.
Регулярные выражения. Поиск повторов слов

    На этом шаге мы рассмотрим однострочник, решающий указанную задачу.

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

Общее описание

    Исследователи большую часть времени тратят на написание, чтение и редактуру научных статей. Редакторы часто жалуются, что авторы постоянно (и очень близко в тексте) используют одни и те же слова. Утилита для проверки написанного программным образом совсем бы не помешала.

Код

    Пусть дано строковое значение, состоящее из слов в нижнем регистре, разделенных пробелами, без каких-либо специальных символов. Необходимо найти подстроку, в которой первое и последнее слова одинаковы (повторяются), причем их разделяет не более десяти слов (пример 5.9).


## Зависимости
import re

## Данные
text = 'if you use words too often words become used'

## Однострочник
style_problems = re.search('\s(?P<x>[a-z]+)\s+([a-z]+\s+){0,10}(?P=x)\s',
                           ' ' + text + ' ')

## Результат
print(style_problems)
Архив с файлом можно взять здесь.

    Действительно ли этот код находит повторы слов?

Принцип работы

    Опять же, мы предполагаем, что text состоит только из разделенных пробелами слов в нижнем регистре. И ищем требуемое в text с помощью регулярного выражения. Оно может показаться запутанным на первый взгляд, но мы рассмотрим его по частям:

'(1)\s(?P<x>[a-z]+)\s+(2)([a-z]+\s+){0,10}(3)(?P=x)\s'

    Мы начинаем с отдельного пробельного символа. Это позволяет гарантировать, что первый найденный фрагмент - целое слово (а не суффикс). Далее мы ищем соответствие поименованной группе x, состоящее из ненулевого числа символов в нижнем регистре от 'a' до 'z', за которым следует ненулевое число пробельных символов (1).

    Затем мы ищем от 0 до 10 слов, каждое из которых состоит из ненулевого числа символов в нижнем регистре от 'a' до 'z', за которым следует ненулевое число пробельных символов (2).

    И заканчиваем поименованной группой x, за которой следует пробельный символ, гарантируя, что последний найденный фрагмент - целое слово (а не префикс) (3).

    Результаты работы этого фрагмента кода выглядят так:

## Результаты 
print(style_problems)
# <re.Match object; span=(12, 35), match=' words too often words '>

    Мы нашли соответствующую регулярному выражению подстроку, стиль которой можно счесть (или не счесть) плохим.

    В данном однострочнике мы свели задачу поиска повторов слов к простейшей и решили этот более простой вариант. Учтите, что на практике придется учитывать и более сложные случаи, например наличие специальных символов, сочетание символов в нижнем и верхнем регистре, чисел и т. д. Либо можно выполнить предварительную обработку и привести текст в желаемый вид: нижний регистр, никаких специальных символов, слова разделяются пробелами.

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




Предыдущий шаг Содержание Следующий шаг