Textdatei segmentieren#

Voraussetzung Textdatei einlesen:

Gegeben: Die Text-Datei www.w3schools.com_python_python_strings_methods.txt (basierend auf https://www.w3schools.com/python/python_strings_methods.asp; Doku: https://docs.python.org/3.11/library/stdtypes.html#string-methods) enthält in semi-strukturierter Form eine Tabelle von String-Funktionen. (Tatsächlich ist das sogar eine CSV-Datei mit TAB als Trennzeichen, aber das wissen wir hier noch nicht.)

Zugehörige Aufgaben:

Die Text-Snippets Dieser Textdatei überführen wir in eine Liste von Listen von Text-Tokens, die wir dann weiter auswerten können.

# psm: python_strings_methods
with open("www.w3schools.com_python_python_strings_methods.txt") as my_file:
    psm_text = my_file.read()

psm_text[:200]
'Quelle\thttps://www.w3schools.com/python/python_strings_methods.asp\ncapitalize()\tConverts the first character to upper case\ncasefold()\tConverts string into lower case\ncenter()\tReturns a centered string'

Anhand von newlines in Zeilen splitten:

Nachlesen: Was macht eine “neue Zeile” aus, insbesondere: Wie wird in Win, Mac, Linux eine neue Zeile codiert?

psm_text_zeilen = psm_text.splitlines()
psm_text_zeilen[:5]
['Quelle\thttps://www.w3schools.com/python/python_strings_methods.asp',
 'capitalize()\tConverts the first character to upper case',
 'casefold()\tConverts string into lower case',
 'center()\tReturns a centered string',
 'count()\tReturns the number of times a specified value occurs in a string']
# anhand von TABs in Tokens splitten
psm_text_tokens = []

for zeile in psm_text_zeilen[1:] : # die erste Zeile enthält etwas anderes, auslassen
    token_list = zeile.split("\t")
    psm_text_tokens.append( token_list )
psm_text_tokens[:5]
[['capitalize()', 'Converts the first character to upper case'],
 ['casefold()', 'Converts string into lower case'],
 ['center()', 'Returns a centered string'],
 ['count()',
  'Returns the number of times a specified value occurs in a string'],
 ['encode()', 'Returns an encoded version of the string']]

Funktionen “von rechts”#

Gesucht:

  • eine Liste von Listen von Funktionen, die es in einer “normalen” Richtung (von links nach rechts) und in einer Richtung “von rechts” gibt

    • z.B. psm_fn_linksrechts = [ ('split', 'rsplit'), ('partition', 'rpartition'), ... ]

Vorübung: Letztlich müssen wir Tests durchführen wie z.B. diesen:

x = "rsplit"
y = "split"

psm_fn_linksrechts = []
if x.endswith( y ):
    psm_fn_linksrechts.append( (x,y) )
    
psm_fn_linksrechts
[('rsplit', 'split')]

Diesen Test müssen wir für jede Kombination aus x und y durchführen – außer x == y.

Lösung:

  • Prüfe für jede denkbare Kombination aus x und y aus der Liste psm_fn_list, ob x.endswith( y )

Das machen wir in einer doppelten Schleife:

psm_fn_list = ['capitalize()', 'casefold()', 'center()', 
                'count()', 'encode()', 'endswith()', 'expandtabs()', 
                'find()', 'format()', 'format_map()', 'index()', 
                'isalnum()', 'isalpha()', 'isascii()', 'isdecimal()', 
                'isdigit()', 'isidentifier()', 'islower()', 'isnumeric()', 
                'isprintable()', 'isspace()', 'istitle() ', 'isupper()', 
                'join()', 'ljust()', 'lower()', 'lstrip()', 'maketrans()', 
                'partition()', 'replace()', 'rfind()', 'rindex()', 
                'rjust()', 'rpartition()', 'rsplit()', 'rstrip()', 
                'split()', 'splitlines()', 'startswith()', 'strip()', 
                'swapcase()', 'title()', 'translate()', 'upper()', 'zfill()']

# BESSER MACHEN:
# Variable psm_fn_list aus psm_text_tokens in einem Einzeiler berechnen

psm_fn_linksrechts = []

for x in psm_fn_list:
    for y in psm_fn_list:
        if x != y and x.endswith( y ):
            psm_fn_linksrechts.append( (x,y) )
psm_fn_linksrechts
[('islower()', 'lower()'),
 ('isupper()', 'upper()'),
 ('lstrip()', 'strip()'),
 ('rfind()', 'find()'),
 ('rindex()', 'index()'),
 ('rpartition()', 'partition()'),
 ('rsplit()', 'split()'),
 ('rstrip()', 'strip()')]

Als List Comprehension:

psm_fn_linksrechts = [ (x,y) 
                      for x in psm_fn_list 
                      for y in psm_fn_list 
                      if x != y and x.endswith( y )
                     ]
psm_fn_linksrechts
[('islower()', 'lower()'),
 ('isupper()', 'upper()'),
 ('lstrip()', 'strip()'),
 ('rfind()', 'find()'),
 ('rindex()', 'index()'),
 ('rpartition()', 'partition()'),
 ('rsplit()', 'split()'),
 ('rstrip()', 'strip()')]

Besser machen (Fingerübung):

  • Interessant, dass wir auch Funktionen bekommen, die mit “is” beginnen. Aber die sind nicht gefragt, besser ausschließen.

  • Wir haben in dieser Lösung noch die Klammern xxx() dabei, wollen die Funktionsnamen aber ohne Klammern.

einzelne Funktionen#

translate() + maketrans()#

Gegeben: ein Text

  • z.B. text = "Hello! Is anybody out there?"

Gesucht: dieser Text,

  • bei dem alle Vokale durch entsprechende Ziffern ausgetauscht sind

  • und “nicht erlaubte” Sonderzeichen (z.B. "?") entfernt sind

  • z.B. "H2ll4! Is 1nyb4dy 45t th2r2"

trans_table = str.maketrans( "aeiou", "12345", "?:.;" )
print(trans_table )
{97: 49, 101: 50, 105: 51, 111: 52, 117: 53, 63: None, 58: None, 46: None, 59: None}
text = "Hello! Is anybody out there?"
text.translate(trans_table)
'H2ll4! Is 1nyb4dy 45t th2r2'

Problem: Bei dieser Lösung müssen wir die nicht erlaubten Sonderzeichen positiv angeben. Aber es gibt sehr viele Sonderzeichen: Sind wir sicher, dass wir alle erfasst haben? Besser wäre es, nur die erlaubten Zeichen anzugeben.

Diskussion und verschiedene Lösungen:

allowed = " -_!" # hier incl. Leerzeichen
text_filtered = ''.join(letter for letter in text if letter.isalnum() or letter in allowed )
text_filtered.translate(str.maketrans("aeiou", "12345"))
'H2ll4! Is 1nyb4dy 45t th2r2'