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

в 7:12, , рубрики: python, инверсия, итерация, оператор, Программирование, симметричная индексация, списки, циклы

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

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

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

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

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

s = 'ПОКОЛЕНИЕ'

print(s[0])       # первый символ строки
print(s[1])       # второй символ строки

print(s[7])       # предпоследний символ строки
print(s[8])       # последний символ строки

выводит:

П
О
И
Е

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

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

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

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

s = 'ПОКОЛЕНИЕ'

print(s[-1])   # последний символ строки
print(s[-2])   # предпоследний символ строки
print(s[-3])   # предпредпоследний символ строки

выводит:

Е
И
Н

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

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

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

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

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

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

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://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js