Програми Python для операцій із рядками

У цьому матеріалі ми розглянемо, як за допомогою мови програмування Python розв’язувати поширені задачі, пов’язані з обробкою текстових даних.

Зокрема, ви навчитеся ідентифікувати, чи є певні рядки паліндромами, анаграмами, а також визначати, чи відповідає їхній регістр формату “заголовкового” написання.

Рядки у Python: Короткий огляд

У Python рядки є вбудованим типом даних, який має значну функціональність. Вони використовуються для зберігання послідовності символів.

Індексування рядків: Подібно до інших ітерованих об’єктів у Python, рядки мають індексацію, що починається з нуля. Це означає, що для рядка довжиною N, допустимі індекси варіюються від 0, 1, 2 і так далі до N – 1.

Python також підтримує можливість доступу до елементів з кінця рядка, використовуючи від’ємні індекси. Таким чином, індекс -1 вказує на останній символ, -2 – на передостанній і так далі.

Незмінність рядків у Python: Важливо відзначити, що рядки в Python є незмінними. Це означає, що після створення рядка ви не можете змінювати його безпосередньо. Однак, ви можете використовувати різноманітні методи рядків для отримання нових рядків з потрібними змінами.

Тепер, коли ми ознайомилися з базовими поняттями про рядки в Python, перейдемо до розгляду кількох простих, але цікавих завдань.

Розпочнімо.

Перевірка, чи є рядок у Python паліндромом

Завдання: Маючи рядок у Python, необхідно визначити, чи є він паліндромом.

У разі позитивної відповіді, функція повинна повернути True, інакше – False.

Отже, перша задача полягає у визначенні, чи є даний рядок паліндромом.

Паліндром – це текстова послідовність, яка читається однаково зліва направо і справа наліво. Наприклад: “радар”, “мадам”, “рівень”, “ротатор”.

Алгоритм для розв’язання цієї задачі включає наступні кроки:

  • Створити перевернуту копію вхідного рядка, за необхідності зберігаючи її в окремій змінній.
  • Порівняти початковий рядок з його перевернутою версією.
  • Якщо обидва рядки ідентичні, це означає, що вхідний рядок є паліндромом. У такому випадку потрібно повернути True і завершити виконання.
  • Якщо початковий рядок не збігається зі своєю перевернутою копією, то він не є паліндромом. В такому випадку потрібно повернути False.

Ключовим етапом є створення перевернутої копії. У Python це можна зробити різними способами.

Розглянемо два основні методи:

  • Використання зрізів рядків
  • Застосування функції reversed() у поєднанні з методом join()

Перевертання рядка у Python за допомогою зрізів

Синтаксис [start: stop: step] дозволяє виділити зріз рядка , починаючи з індексу start, і закінчуючи, але не включаючи індекс stop, з заданим кроком step.

  • Якщо параметр start не вказано, то зріз починається з початку рядка.
  • Якщо параметр stop не вказано, то зріз продовжується до кінця рядка.
  • Від’ємні значення step дозволяють обходити рядок у зворотному напрямку.

Отже, вираз [::-1] створить перевернуту копію рядка.

У наступному кодовому блоці представлено визначення функції is_palindrome(), яка приймає рядок як вхідний параметр і повертає True або False залежно від того, чи є цей рядок паліндромом.

У цій функції для створення перевернутої копії рядка використано зрізи рядків.

def is_palindrome(this_str):
    rev_str = this_str[::-1]
    if (this_str == rev_str):
      return True
    else:
      return False

▶️ Тепер, коли функцію визначено, можна викликати її з будь-яким допустимим рядком як аргументом.

is_palindrome("racecar")
  True

У наведеному вище прикладі рядок “racecar” є паліндромом. Тому функція is_palindrome() повертає True, як і очікувалося.

Спробуємо викликати функцію з рядком, який не є паліндромом, наприклад, “river”.

is_palindrome("river")
  False

Як бачимо, функція повертає False, що є правильним результатом. ✅

Перевертання рядка у Python за допомогою reversed() та join()

У Python для перевертання рядка можна використовувати метод join() у поєднанні з функцією reversed().

  • Функція reversed() створює ітератор у зворотному порядку для символів у рядку.
  • Метод join() використовується для з’єднання цих символів у зворотній послідовності.

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

def is_palindrome(this_str):
    rev_str="".join(reversed(this_str))
    if (this_str == rev_str):
      return True
    else:
      return False

Функцію is_palindrome() також можна застосувати всередині генератора списку для фільтрування паліндромів з набору рядків.

str_list = ["refer","blue","level","12321","dragon"]

  palindromes = [string for string in str_list if is_palindrome(string)]
  print(palindromes)
  # Output
  ['refer', 'level', '12321']

Пояснення наведеного вище коду:

  • Проходимо через кожен рядок у списку str_list і викликаємо функцію is_palindrome().
  • Якщо функція is_palindrome() повертає True, то рядок додається до списку palindromes.

Як видно у виводі, palindromes – це список, що містить всі паліндромні рядки з str_list.

Перевірка, чи є два рядки в Python анаграмами

Ще одне поширене завдання, яке може виникнути під час співбесіди, – це визначити, чи є два рядки, str1 та str2, анаграмами.

Два рядки вважаються анаграмами, якщо вони складаються з абсолютно ідентичної кількості однакових символів. Це означає, що один рядок можна отримати, переставляючи символи іншого рядка.

Приклади анаграм: “ніч – чін”, “літо – тіло”, “кот – ток”.

Перевірка наявності анаграм за допомогою об’єкта Counter у Python

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

Це можна спростити, використовуючи об’єкт Counter з модуля itertools. Об’єкт Counter повертає словник Python, де ключами є символи, а значеннями – відповідні кількості їх входжень.

Розглянемо, наприклад, рядки “save” та “vase”, як показано нижче.

str1 = "save"
  str2 = "vase"

Тут c1 та c2 – це об’єкти Counter, що містять частоту входження символів рядків str1 та str2 відповідно.

from collections import Counter
  c1 = Counter(str1)
  c2 = Counter(str2)
  print(c1)
  print(c2)
  c1 == c2

  # Output
  Counter({'s': 1, 'a': 1, 'v': 1, 'e': 1})
  Counter({'v': 1, 'a': 1, 's': 1, 'e': 1})
  True

Вираз c1 == c2 повертає True, оскільки str1 та str2 є анаграмами.

Використовуючи цю логіку, можна визначити функцію are_anagrams() з двома параметрами, word1 та word2. У тілі функції ми перевіряємо, чи Counter(word1) == Counter(word2).

def are_anagrams(word1, word2):
    if Counter(word1) ==  Counter(word2):
      return True
    else:
      return False

▶️ Для перевірки викличемо are_anagrams() з str1 та str2 як аргументами. Оскільки str1 та str2 є анаграмами (“save” та “vase”), функція поверне True, що є правильним результатом.

are_anagrams(str1, str2)
  True

Перевірка анаграм за допомогою відсортованих копій рядків

Існує ще один спосіб перевірити, чи є рядки анаграмами.

Якщо два рядки є анаграмами, їх відсортовані копії будуть ідентичними.

Тому ми можемо переписати функцію are_anagrams() і перевірити, чи збігається відсортована версія str1 з відсортованою версією str2. Якщо вони рівні, то рядки є анаграмами, інакше – ні.

Використовуючи наведений підхід, функцію are_anagrams() можна переписати наступним чином.

def are_anagrams(word1, word2):
    if sorted(word1) ==  sorted(word2):
      return True
    else:
      return False

Тепер зробимо кілька викликів функції.

  • Рядки “elbow” та “below” є анаграмами, тому функція are_anagrams() повертає True.
  • Рядки “state” та “tasted” не є анаграмами, і функція повертає False.
are_anagrams("below","elbow")
  True

  are_anagrams("state","tasted")
  False

Перевірка, чи рядок у Python має “заголовковий” регістр

Ось наше останнє завдання в цьому матеріалі.

Завдання. Задано рядок, що представляє ім’я особи (ім’я та прізвище).

Необхідно перевірити, чи написана перша літера імені та прізвища у верхньому регістрі.

Такий формат написання, коли перша літера кожного слова є великою, називається “заголовковим” регістром.

Тому потрібно визначити, чи відповідає ім’я “заголовковому” регістру:

1. У разі позитивної відповіді, потрібно вивести повідомлення про те, що рядок уже відформатовано у “заголовковому” регістрі.

2. У іншому випадку, потрібно повернути копію рядка, відформатовану у “заголовковому” регістрі.

  • Python має вбудований метод string istitle(), який перевіряє, чи рядок відповідає “заголовковому” регістру.

.istitle() повертає True, якщо рядок відформатовано в “заголовковому” регістрі, інакше повертає False.

  • Метод Python title() повертає копію рядка, відформатовану в “заголовковому” регістрі.

Тепер можна використати ці два методи для розв’язання задачі.

Визначимо функцію check_titlecase(), яка приймає ім’я як аргумент.

  • Використаємо метод istitle() для перевірки, чи вхідний рядок відформатовано у “заголовковому” регістрі.
  • Якщо повертається True, то виводимо повідомлення, що рядок вже має “заголовковий” регістр.
  • У іншому випадку, використовуємо метод title() і повертаємо копію рядка, відформатовану у “заголовковому” регістрі.

У наступному кодовому блоці показано визначення функції check_titlecase().

def check_titlecase(name):
    if name.istitle():
      print(f"'{name}' is already formatted in title case.")
    else:
      return name.title()

Тепер викличемо метод check_titlecase() з аргументом.

check_titlecase("jane smith")

  # Output
  Jane Smith

У виводі вище можна побачити, що рядок “jane smith” тепер відформатований у “заголовковому” регістрі.

▶️ Розглянемо інший приклад.

check_titlecase("agatha Christie")

  # Output
  Agatha Christie

Тепер викличемо функцію з рядком, який вже відформатований у “заголовковому” регістрі.

check_titlecase("Grace Hopper")

  # Output
  'Grace Hopper' is already formatted in title case.

Ми отримали повідомлення про те, що рядок вже відформатовано у “заголовковому” регістрі, отже, функція працює коректно.

Висновок 👩‍🏫

Підсумуємо завдання, які ми розглянули:

  • Щоб перевірити, чи рядок є паліндромом, необхідно перевірити, чи збігається рядок зі своєю перевернутою версією. Для перевертання рядка можна використовувати зрізи або вбудовані методи.
  • Для визначення, чи є два рядки анаграмами, необхідно перевірити, чи однакові їхні відсортовані копії. Для сортування рядка використовуйте вбудовану функцію sorted().
  • Щоб перевірити, чи ім’я написане у “заголовковому” регістрі, використовуйте метод .istitle() для перевірки, та метод .title() для отримання копії рядка з “заголовковим” регістром.

Сподіваємося, вам сподобався цей огляд задач обробки рядків у Python. У якості наступного кроку можете вивчити генератори списків у Python або ознайомитися з оператором нерівності.

Вдалого вам навчання та програмування!🎉