Шаг 26.
Однострочники Python. Трюки Python. Извлечение окружения вхождений подстрок с помощью срезов (окончание)

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

Код

    Наша цель - найти конкретный текст внутри многострочного строкового значения. Затем необходимо вернуть его непосредственное окружение в виде 18 символов, окружающих найденное вхождение. Извлечение окружения вместе с искомым текстом позволяет увидеть текстовый контекст найденной строки - подобно тому, как Google выводит фрагменты текста, окружающие искомое ключевое слово. В примере 2.5 мы ищем строку символов 'SQL' в письме Amazon к акционерам - вместе с непосредственным ее окружением в виде 18 окружающих строку 'SQL' символов.


Пример 2.5. Однострочное решение для поиска в тексте последовательностей символов и их непосредственного окружения
## Данные
letters_amazon = '''
We spent several years building our own database engine,
Amazon Aurora, a fully-managed MySQL and PostgreSQL-compatible
service with the same or better durability and availability as
the commercial engines, but at one-tenth of the cost. We were
not surprised when this worked.
'''

## Однострочник
find = lambda x, q: x[x.find(q) - 18:x.find(q) + 18] if q in x else -1

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

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

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

    Мы описали лямбда-функцию с двумя аргументами: строковым значением x и строкой запроса q, которую мы будем искать в тексте. Эту лямбда-функцию мы присваиваем переменной с именем find. Функция find(x, q) ищет строку запроса q в строке текста x.

    Если поисковый запрос q не встречается в строковом значении x, мы возвращаем результат -1. В противном случае вырезаем из строки текста первое вхождение поискового запроса плюс 18 символов слева и 18 символов справа в качестве окружения запроса. Индекс первого вхождения q в x мы находим с помощью строкового метода x.find(q), который вызываем дважды: чтобы определить индекс начала и индекс конца среза, но оба вызова возвращают одно значение, поскольку ни запрос q, ни строковое значение x не меняются.

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

    Это обсуждение проливает свет на немаловажный компромисс: ограничивая себя одной строкой кода, мы лишаемся возможности описать и повторно использовать вспомогательную переменную для хранения индекса первого вхождения поискового запроса. Вместо этого нам приходится выполнять один и тот же метод find() для вычисления индекса начала среза (и уменьшить результат на 18 позиций индекса) и индекса конца среза (и увеличить результат на 18 позиций индекса). Далее мы познакомимся с более эффективном способом поиска паттернов в строках текста (с помощью регулярных выражений), позволяющем решить эту проблему.

    При поиске строки символов 'SQL' в письме Amazon к акционерам мы находим следующее вхождение поискового запроса в тексте:

## Результат
print(find(letters_amazon, 'SQL'))
# a fully-managed MySQL and PostgreSQL

    В результате получаем искомую строку символов и несколько слов около нее в качестве контекста. Срезы - важнейший элемент базового образования разработчика на языке Python. Давайте рассмотрим еще один пример однострочника.

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




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