V tomto průvodci si procvičíme psaní programů v Pythonu, které řeší časté úlohy spojené s prací s textovými řetězci.
Konkrétně se naučíme, jak v Pythonu ověřit, zda je daný řetězec palindromem, anagramem, a zda je zapsán v takzvaném „title case“.
Stručný pohled na řetězce v Pythonu
Řetězce jsou v Pythonu základními a efektivními datovými typy. Umožňují ukládat posloupnosti znaků.
Indexování řetězců: Stejně jako u všech iterovatelných struktur v Pythonu, i řetězce jsou indexovány od nuly. To znamená, že pro řetězec o délce N jsou platné indexy 0, 1, 2, až N – 1.
Python také nabízí možnost záporného indexování, které umožňuje přístup k prvkům od konce řetězce. Index -1 tedy odpovídá poslednímu znaku, -2 předposlednímu a tak dále.
Neměnnost řetězců: Řetězce v Pythonu jsou navíc neměnné, což znamená, že je nelze upravovat přímo. Nicméně, lze nad nimi provádět různé řetězcové operace, které vracejí nové řetězce s požadovanými úpravami.
Nyní, když máme stručný přehled o základech řetězců v Pythonu, můžeme se pustit do řešení několika jednoduchých, ale zajímavých úloh.
Začněme.
Ověření, zda je řetězec palindrom
Úloha: Máme daný řetězec v Pythonu a potřebujeme zjistit, zda se jedná o palindrom.
Pokud ano, funkce vrátí True, jinak False.
Palindrom je slovo nebo věta, která se čte stejně zleva doprava i zprava doleva. Příklady zahrnují slova jako „radar“, „kajak“, „madam“ nebo „rotor“.
Postup řešení:
- Vytvoříme obrácenou kopii zadaného řetězce (případně ji uložíme do nové proměnné).
- Porovnáme původní řetězec s jeho obrácenou verzí.
- Pokud jsou identické, řetězec je palindrom a vrátíme True.
- V opačném případě (pokud se řetězce liší) vrátíme False.
Klíčovou operací je tedy vytvoření obrácené kopie řetězce. V Pythonu existuje několik způsobů, jak toho dosáhnout.
Podíváme se na dva hlavní přístupy:
- Použití „slicingu“ (řezů) řetězce
- Použití funkce reversed() a metody join().
Obrácení řetězce pomocí „slicingu“
Syntaxe <řetězec>[start:stop:step] vrací výsek z řetězce, a to od indexu ‚start‘ (včetně) po index ‚stop‘ (vyjma), s krokem ‚step‘.
- Pokud vynecháme ‚start‘, řez začíná na začátku řetězce.
- Pokud neuvedeme ‚stop‘, řez pokračuje až do konce řetězce.
- Záporná hodnota ‚step‘ umožňuje vytvořit řez odzadu.
Zápis <řetězec>[::-1] tak vrací obrácenou kopii řetězce.
Následující kód definuje funkci is_palindrome(), která jako vstup bere řetězec a vrací True, pokud je palindromem, a False, pokud ne.
V této funkci používáme právě slicing k získání obrácené kopie řetězce.
def is_palindrome(this_str): rev_str = this_str[::-1] if (this_str == rev_str): return True else: return False
▶️ Funkce je připravena, můžeme ji vyzkoušet s různými řetězci.
is_palindrome("racecar") True
V tomto případě je „racecar“ palindrom, takže funkce vrátí True, jak se očekává.
Nyní zkusíme funkci použít na řetězec, který palindromem není, například „river“.
is_palindrome("river") False
A výsledek je False, což je správně. ✅
Obrácení řetězce pomocí reversed() a join()
V Pythonu můžeme pro obrácení řetězce použít funkci reversed() v kombinaci s metodou join().
- Funkce reversed() vrací iterátor, který prochází znaky řetězce od konce.
- Metoda join() pak spojí tyto znaky do nového řetězce, který je tak obrácen.
S použitím této metody můžeme přepsat funkci is_palindrome(), jak je uvedeno v následujícím kódu:
def is_palindrome(this_str): rev_str="".join(reversed(this_str)) if (this_str == rev_str): return True else: return False
Funkci is_palindrome() můžeme také využít v list comprehension k vyfiltrování palindromů z většího seznamu řetězců.
str_list = ["refer","blue","level","12321","dragon"] palindromes = [string for string in str_list if is_palindrome(string)] print(palindromes) # Output ['refer', 'level', '12321']
Kód funguje takto:
- Prochází se seznam str_list a pro každý řetězec se volá funkce is_palindrome().
- Pokud is_palindrome() vrátí True, daný řetězec se přidá do seznamu ‚palindromes‘.
Výstupem je seznam všech palindromických řetězců obsažených v ‚str_list‘.
Ověření, zda jsou dva řetězce anagramy
Další častá úloha při programovacích pohovorech je zjistit, zda jsou dva dané řetězce anagramy.
Dva řetězce jsou považovány za anagramy, pokud se skládají ze stejných znaků ve stejném počtu. Zjednodušeně řečeno, jeden z řetězců lze získat přeskupením znaků v druhém.
Příklady anagramů jsou „silent“ a „listen“, „tea“ a „eat“, nebo „dormitory“ a „dirty room“.
Kontrola anagramů pomocí objektu Counter
Jednou z možností je spočítat výskyt každého znaku v obou řetězcích a porovnat, zda jsou počty shodné.
To lze snadno provést pomocí objektu Counter z modulu collections. Counter vrací slovník, kde klíči jsou znaky a hodnotami počty jejich výskytů.
Uvažujme řetězce „save“ a „vase“, jak je uvedeno níže.
str1 = "save" str2 = "vase"
c1 a c2 jsou instance objektu Counter, obsahující počty výskytů znaků v řetězcích str1 a 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 vrací True, protože ‚str1‘ a ‚str2‘ jsou anagramy.
Na základě této logiky můžeme definovat funkci are_anagrams(), která jako vstup bere dva řetězce ‚word1‘ a ‚word2‘. Uvnitř funkce ověříme, zda Counter(word1) == Counter(word2).
def are_anagrams(word1, word2): if Counter(word1) == Counter(word2): return True else: return False
▶️ Funkci are_anagrams() zavoláme s ‚str1‘ a ‚str2‘ jako argumenty. Protože se jedná o anagramy („save“ a „vase“), funkce vrátí True, což je správně.
are_anagrams(str1, str2) True
Kontrola anagramů pomocí seřazených kopií
Existuje i další způsob, jak ověřit, zda jsou dva řetězce anagramy.
Pokud jsou dva řetězce anagramy, jejich seřazené kopie budou identické.
Můžeme tedy funkci are_anagrams() přepsat tak, aby porovnávala, zda seřazená verze ‚str1‘ je stejná jako seřazená kopie ‚str2‘. Pokud ano, řetězce jsou anagramy.
Pomocí této metody můžeme funkci are_anagrams() definovat následovně:
def are_anagrams(word1, word2): if sorted(word1) == sorted(word2): return True else: return False
Nyní provedeme několik volání funkce.
- Řetězce „below“ a „elbow“ jsou anagramy, takže funkce are_anagrams() vrátí True.
- A řetězce „state“ a „tasted“ nejsou anagramy, funkce tedy vrací False.
are_anagrams("below","elbow") True are_anagrams("state","tasted") False
Ověření, zda je řetězec v „title case“
A zde je poslední úloha pro tento tutoriál.
Úloha: Máme zadaný řetězec – jméno osoby (křestní a příjmení).
Potřebujeme zkontrolovat, zda je první písmeno křestního i příjmení velké.
Tento formát, kdy je první písmeno každého slova velké, se nazývá „title case“.
Musíme tedy ověřit, zda je dané jméno zapsáno v „title case“:
1. Pokud ano, vypíšeme zprávu, že formátování je v pořádku.
2. Pokud ne, vrátíme kopii řetězce upravenou do „title case“.
- Python má vestavěnou metodu istitle(), která ověří, zda je řetězec zapsán v „title case“.
Metoda <řetězec>.istitle() vrací True, pokud je <řetězec> zapsán v „title case“, jinak vrací False.
- Metoda title() pak vrací kopii řetězce, upravenou do „title case“.
Tyto dvě metody nám tedy umožní vyřešit danou úlohu.
Definujeme funkci check_titlecase(), která bere jako argument jméno.
- U vstupního řetězce zavoláme metodu istitle() a ověříme, zda je ve formátu „title case“.
- Pokud je výsledek True, vypíšeme zprávu, že řetězec již je v „title case“.
- V opačném případě zavoláme metodu title() a vrátíme kopii řetězce v „title case“.
Definice funkce check_titlecase() je uvedena v následujícím kódu:
def check_titlecase(name): if name.istitle(): print(f"'{name}' is already formatted in title case.") else: return name.title()
Nyní zavoláme metodu check_titlecase() s argumentem.
check_titlecase("jane smith") # Output Jane Smith
Na výstupu vidíme, že řetězec „jane smith“ byl upraven do „title case“.
▶️ Podívejme se na další příklad.
check_titlecase("agatha Christie") # Output Agatha Christie
Nyní zavoláme funkci s řetězcem, který již je v „title case“.
check_titlecase("Grace Hopper") # Output 'Grace Hopper' is already formatted in title case.
Zobrazí se zpráva, že řetězec je již v „title case“, a funkce funguje správně.
Závěr 👩🏫
Shrňme si tedy úlohy, které jsme v tomto tutoriálu probrali.
- Pro ověření, zda je řetězec palindromem, ověříme, zda se řetězec shoduje se svou obrácenou verzí. K obrácení můžeme použít slicing nebo vestavěné funkce.
- Pro ověření, zda jsou dva řetězce anagramy, ověříme, zda se jejich seřazené kopie shodují. K seřazení můžeme použít vestavěnou funkci sort().
- Pro ověření, zda je řetězec v „title case“, použijeme metodu istitle(). K úpravě řetězce do „title case“ pak metodu title().
Doufám, že se vám tento tutoriál o práci s řetězci v Pythonu líbil. Pro další studium doporučuji se seznámit s „list comprehension“ nebo s operátorem nerovnosti v Pythonu.
Přeji příjemné učení a kódování!🎉