Симметричная индексация в Python

—

от автора

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

Индексация последовательностей

В языке Python достаточно удобно реализована индексация последовательностей. Мы легко можем обращаться к элементам последовательности от начала, используя индексы, начиная с нуля. То есть первый элемент последовательности имеет индекс 0, второй элемент последовательности имеет индекс 1 и так далее. В общем случае i-й элемент последовательности от начала имеет индекс i - 1.

Приведенный ниже код:

s = 'ПОКОЛЕНИЕ'  print(s[0])       # первый символ строки print(s[1])       # второй символ строки  print(s[7])       # предпоследний символ строки print(s[8])       # последний символ строки

выводит:

П О И Е

Обратите внимание: из-за того что нумерация начинается с нуля, а не с единицы, получается, что последним допустимым индексом является индекс на единицу меньший, чем длина последовательности.

Мы также легко можем обращаться к элементам последовательности от конца, используя отрицательные индексы, начиная с -1. То есть последний элемент (первый элемент с конца) последовательности имеет индекс -1, предпоследний элемент (второй элемент с конца) последовательности имеет индекс -2 и так далее. В общем случае i-й элемент последовательности от конца имеет индекс -i.

Приведенный ниже код:

s = 'ПОКОЛЕНИЕ'  print(s[-1])   # последний символ строки print(s[-2])   # предпоследний символ строки print(s[-3])   # предпредпоследний символ строки

выводит:

Е И Н

Симметричная индексация и оператор ~

Как мы видим, в Python индексация от начала и от конца последовательности является несимметричной. Действительно, элементу с индексом 0 от начала соответствует симметричный элемент с индексом -1 от конца, элементу с индексом 1 от начала соответствует симметричный элемент с индексом -2 от конца и так далее.

Ниже приведена таблица соответствия индексов симметричных элементов от начала и конца последовательности.

Индекс от начала

Индекс от конца

0

-1

1

-2

2

-3

3

-4

4

-5

5

-6

...

...

В общем случае элементу с индексом i от начала будет соответствовать симметричный элемент с индексом -(i + 1) от конца.

Не все знают, но в Python для целых чисел можно использовать унарный оператор побитовой инверсии ~. Данный оператор «переворачивает» биты в двоичном представлении числа, выполняя операцию побитового отрицания: 1 преобразуется в 0, а 0 — в 1.

В общем виде оператор ~ преобразует целое число n в соответствии с правилом:

\sim n = -(n + 1)

То есть положительные числа преобразуются в отрицательные со сдвигом на единицу.

Приведенный ниже код:

print(~0) print(~1) print(~2) print(~3)  print(~-1) print(~-2) print(~-3) print(~-4)

выводит:

-1 -2 -3 -4 0 1 2 3

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

В качестве примера напишем функцию is_palindrome(), использующую симметричную индексацию с помощью оператора ~ для проверки входной строки на палиндром.

Приведенный ниже код:

def is_palindrome(s: str) -> bool:         for i in range(len(s) // 2):                 if s[i] != s[~i]:                         return False         return True   print(is_palindrome('abccba')) print(is_palindrome('abcpba'))

выводит:

True False

По сути, выражение s[i] != s[~i] эквивалентно выражениям s[i] != s[-i - 1] и s[i] != s[len(s) - i - 1], однако является более красивым и компактным вариантом записи.

В качестве заключения. Скорее всего, вы нечасто будете использовать только что изученную возможность использования оператора ~ для реализации симметричной индексации. Однако знать такое будет совсем не лишним.

Присоединяйтесь к нашему телеграм-каналу, будет интересно и познавательно!

❤️Happy Pythoning!?


ссылка на оригинал статьи https://habr.com/ru/articles/818479/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *