11. Práce s textem

11.1. Práce s textem

Pokročilá práce s řetězci

Čtení a zápis do souborů

Oficiální dokumentace

input_file = open("input.txt", "r")         # otevreni souboru pro cteni
content = input_file.read()                 # nacteni celeho obsahu souboru do retezce
lines = input_file.readlines()              # nacteni souboru souboru jako seznam radku
output_file = open("output.txt", "w")       # otevreni souboru pro zapis
output_file.write("Some sentence.")         # zapis retezce do souboru
some_file.close()                           # uzavreni souboru

# doporucovana konstrukce with, ktera zajisti automaticke uzavreni souboru:
with open("input.txt", "r") as input_file:
    pass

11.1.1. “head” / “tail”

Načtěte soubor alice-in-wonderland.txt a naprogramujte funkce:

  1. head, která vypište prvních n řádků obsahu souboru,

  2. tail, která vypište posledních n řádků obsahu souboru.

def head(filename: str, n: int) -> None:
    pass

head("alice-in-wonderland.txt", 3)
#
# ALICE’S ADVENTURES IN WONDERLAND
#

def tail(filename: str, n: int) -> None:
    pass

tail("alice-in-wonderland.txt", 3)
# all their simple sorrows, and find a pleasure in all their simple joys,
# remembering her own child-life, and the happy summer days.
#

11.1.2. Každé druhé slovo

Načtěte soubor lorem-ipsum.txt a vypište každé druhé slovo, které se v něm nachází.

def every_second(filename: str) -> None:
    pass

every_second("lorem-ipsum.txt")
# ipsum sit consectetur elit, do tempor ut et magna Rhoncus purus
# enim Risus tristique aliquet. in quam orci eu Scelerisque imperdiet
# fermentum vel porta

11.1.3. Nejčastější slova

Načtěte soubor sherlock-holmes.txt a vypište 10 nejčastěji se vyskytujících slov v textu. Pro zajímavost se omezte pouze na slova délky 3 a více.

def most_freq_words(filename: str) -> None:
    pass

most_freq_words('sherlock-holmes.txt')

11.1.4. Průměrný počet slov ve větě

Analyzujte text v souboru alice-in-wonderland.txt a vraťte průměrný počet slov ve větě.

def average_sentence_len(filename: str) -> float:
    pass

print(average_sentence_len('alice-in-wonderland.txt'))

11.1.5. Frekvence písmen

Proveďte frekvenční analýzu některého z výše uvedených souborů. Vypište, kolikrát se v textu vyskytují jednotlivá písmena.

Tip: pro ověření, že je daný znak písmeno, můžete použít funkci isalpha.

def freq_analysis(filename: str) -> None:
    pass

freq_analysis('my_file.txt')

11.1.6. Podmíněná frekvenční analýza

Pro každé písmeno v textu vypište 5 písmen, které za ním následují nejčastěji. Můžete využít například soubor devatero_pohadek.txt.

def cond_freq_analysis(filename: str) -> None:
    pass

cond_freq_analysis('devatero_pohadek.txt')

11.1.7. Imitace textu

Napište funkci text_imitation(filename, length), která analyzuje text v souboru filename. Funkce pak vygeneruje pseudo-náhodný text o length slovech. Text se generuje po slovech. Další generované slovo se náhodně vybírá z těch, které v původním textu po naposledy vygenerovaném slově následovaly.

def text_imitation(filename: str, length: int) -> None:
    pass

text_imitation('devatero_pohadek.txt', 10)

11.1.8. Imitace textu po písmenech

Upravte vaše předchozí řešení tak, aby vytvářelo slova a to po jednotlivých písmenech.

11.1.9. Analýza jmen

Načtěte soubor jmena.csv. Implementujte funkci most_common_names(filename), která ze souboru vypíše count nejčastěji užívaných jmen (globálně).

def most_common_names(filename: str, count: int) -> None:
    pass

most_common_names('jmena.csv', 10)

11.1.10. Analýza jmen II

Upravte předchozí funkci tak, aby jako parametr brala ještě seznam roků. Funkce vypíše count nejčastějších jmen v letech, které dostane v seznamu.

def most_common_names_years(filename: str, count: int, years: List[int]) -> None:
    pass

most_common_names_years('jmena.csv', 10, [2005, 1996, 2003])

11.1.11. Zpracování jmen

Napište funkce, která přečte všechny jména v souboru NAMES.txt, zpracuje je tak, aby měla velké pouze první počáteční písmeno (JOHN -> John) a seřadí je v abecedě. Po té je uloží do jiného souboru.

def process_names(input_filename: str, output_filename: str) -> None:
    pass

process_names('NAMES.txt', 'names.txt')

11.2. Regulární výrazy

_images/regular_expressions.png

Regulární výraz (regular expression), označovaný též zkráceně jako regexp či regex je speciální řetězec znaků, který představuje určitý vzor pro textové řetězce. Regulární výraz je tedy nějaký obecný popis, který vždy odpovídá určité skupině řetězců (např.: email, html tag, datum…). Můžeme je využít ke kontrole vstupu, hledání a nahrazování v textu, parsování html a mnoha dalším úkolům.

O regulárních výrazech bylo mnoho napsánu a existuje mnoho návodů a taháků: regularnivyrazy.info, python.org, Wikipedia, Cheat Sheet, OverAPI a další. Existují i weby, kde si lze práci s regulárními výrazy snadno vyzkoušet online (např.: pythex.org). Můžete je také procvičit na Tutorovi.

Pro práci s regulárními výrazy v Pythonu lze využít knihovnu re

Raw string

Protože zpětná lomítka mají speciální význam také v regulárních výrazech (a tedy jich obvykle obsahují hodně), vyhovovalo by nám více takové chování, kdy by se zpětná lomítka v řetězci nijak neinterpretovala. Toho lze dosáhnout přidáním znaku r těsně před samotný řetězec, např. r’raw string with ‘.

11.2.1. Celá čísla

Napište funkci is_integer(string), která vrátí True pokud zadaný string je celé číslo.

import re

def is_integer(string: str) -> bool:
    pass

def test_is_integer() -> None:
    assert is_integer("42") == True
    assert is_integer("-42") == True
    assert is_integer("4a2") == False

11.2.2. Čísla

Napište funkci is_number(string), která vrátí True pokud zadaný string je číslo.

import re

def is_number(string: str) -> bool:
    pass

def test_is_number() -> None:
    assert is_number("42.01") == True
    assert is_number("-42") == True
    assert is_number("4.b") == False
    assert is_number("42.") == False

11.2.3. Jména

Využijte soubor jmen, které jste vytvořili ve cvičení Zpracování jmen. Funkce search_in_file(pattern, filename) vypíše z daného souboru všechny řádky, které odpovídají vzoru. Pomocí této funkce vypište všechny jména která

  1. obsahují oo

  2. obsahují alespoň 3 znaky o (ne nutně po hned sobě)

  3. obsahují pouze samohlásky

  4. obsahují pouze souhlásky [stačí přidat jediný znak do předchozího vzoru]

  5. začínají na B nebo D a končí na w nebo z

  6. obsahují buď inf nebo rec

  7. kromě prvního a posledního písmene obsahují pouze samohlásky a mají přesně 5 písmen

  8. začínají a končí na A a mají nejvýše 4 písmena

  9. začínají na N nebo M a obsahují alespoň 5 samohlásek

  10. kromě a můžou obsahovat nejvýše 2 jiná písmena, což ale můžou být jedině l, m nebo n

# vypise radky, ktere splnuji zadany vzor
def search_in_file(pattern: str, file_name: str) -> None:
    with open(file_name) as f:
        lines = f.read().split('\n')        # nacteme vsechny radky do seznamu
        for line in lines:                  # prochazime radky a hledame shodu
            if re.search(pattern, line):
                print(line)

search_in_file(r'.*',  'names.txt')

11.2.4. Zpracování CSV

Ze souboru students.csv vypište následující statistiky:

  1. seznam všech křestních jmen

  2. seznam všech použitých křestních jmen (bez opakování) s počtem jejich výskytů

  3. seznam všech použitých křestních jmen s počtem jejich výskytů začínající daným písmenem

  4. řaďte jména podle abecedy

  5. pro každého člověka informaci o studovaném semestru v následujícím formátu: 50668: 1. semestr 1. rocniku, 43583 : 5. semestr 1 cyklu

  6. další informace (třeba rozložení mezi fakultami)

names("students.csv", "s")
# Samuel 3
# Sandra 1
# Sebastian 1

semesters("students.csv")
# 50668 : 1. semestr 1 rocniku
# 421714: 2. semestr 1 rocniku
# 564138: 1. semestr 1 rocniku
# 43583 : 5. semestr 1 cyklu
# 81908 : 5. semestr 1 cyklu
# 844632: 1. semestr 1 rocniku
# 798639: 1. semestr 1 rocniku
# ....
Next Section - 12. Bitmapová grafika