Verbesserungsvorschläge für mein Python Skript: Polindrome finden?

2 Antworten

Erstens: es heißt Palindrom.

Zweitens, nur ein paar eher schnelle Beobachtungen.

    for i in range(len(word)-1, 0-1, -1): #Wort rueckwaerts zusammen basteln
        reverse = reverse + word[i]

Klar, kann man machen, aber das geht auch viel einfacher:

>>> w = "nasenbär"
>>> w[::-1]
'räbnesan'

Das hier:

    for c in removable: # Zeug entfernen
        word = word.replace(c, '')
    for c in string.punctuation: #Sonderzeichen entfernen
        word = word.replace(c, '')
    for c in string.whitespace: #Leerzeichen entfernen, da sonst falsche Ergebnisse entstehen
        word = word.replace(c, '')

Kann man auch vereinfachen, indem man erst eine Übermenge aller dieser Listen/Sets bildet und dann einmal durchgeht. Du kannst dir auch str.translate() anschauen.

Sowas in der Art:

    if ein_boolescher_ausdruck
        return True
    else:
        return False

ist unnötig kompliziert. Du kannst doch den booleschen Wert direkt zurückgeben.

Das hier:

        if check_polindrome(word) == True:
            polindrome.append(word)
        else:
            continue

lässt sich eindampfen auf:

        if check_polindrome(word):
            polindrome.append(word)

Das hier:

for i in range(0, len(lines)):

brauchst du allenfalls, wenn du den Index mitzählen willst. Über eine Liste (oder sonst ein iterable) kannst du doch viel einfacher iterieren:

for line in lines:
   # tu was mit line
alfredo153  10.11.2020, 18:27

...der letzte Fall ist auch zweifelhaft, weil du hier durch die Liste an Lines durchiterierst und sie gleichzeitig veränderst. Mach das nicht. Es ist auch gar nicht nötig.

    lines[i] = lines[i].split(' ')
0
PythonNeuling00 
Fragesteller
 10.11.2020, 19:28
@alfredo153

Verbesserter Code:

#!/bin/python3
#Palindrome-Woerter in Textdatei erkennen
import string

#Funktion zum Erkennen von Palindromen
def check_palindrome(word):
    reverse = ''
    removable = string.punctuation + string.whitespace + string.digits
    for c in removable: #Leerzeichen entfernen, da sonst falsche Ergebnisse entstehen
        word = word.replace(c, '')
    if word in string.punctuation or word in string.whitespace: #Leer- und Sonderzeichen abfangen
        return False
    for c in word[::-1]: #Wort rueckwaerts zusammen basteln
        reverse = reverse + c
    if reverse.lower() == word.lower(): #Rueckwaerts-Wort mit vorwaerts-Wort vergleichen
        return True
    else:
        return False

#Den Benutzer eine Textdatei oeffnen lassen
file = input('Path to file: ')
palindrome = []

try:
    with open(file, 'r') as f:
        lines = f.readlines()
except FileNotFoundError:
    print('File not found!')
    exit(0)

#Einzelne Woerter im Text der Funktion check_palindrome uebergeben
for line in lines:
    line = line.split(' ')
    for word in line:
        if check_palindrome(word):
            palindrome.append(word)
        else:
            continue

#Ergebnis anzeigen
print(len(palindrome), ' found!\n')
for i in range(len(palindrome)):
    print(palindrome[i].replace('\n', '')) #\n in Wort entfernen, da sonst zu viele Leerzeichen bei Output

Wenn ich aber

line = line.split(' ')

nicht mache, dann bekomme ich den gesamten Text in einzelnen Buchstaben im Output.

0

alfredo hat schon das Meiste gesagt. Hier noch ein paar konkrete Tipps:

#!/usr/bin/env python3

(siehe hier)

#Funktion zum Erkennen von Polindromen
def check_polindrome(word):
    reverse = ''

    # 1. brauchst du nicht, denn das ist alles whitespace:
    #removable = ['\n', '\t', '\r']
    #for c in removable: # Zeug entfernen
    #    word = word.replace(c, '')

    # 2. kann man machen, ist aber teuer.
    #    Verwende lieber str.translate():
    #for c in string.punctuation: #Sonderzeichen entfernen
    #    word = word.replace(c, '')
    #for c in string.whitespace: #Leerzeichen entfernen, da sonst falsche Ergebnisse entstehen
    #    word = word.replace(c, '')
    word = word.translate(str.maketrans('', '', string.punctuation))

    # 3. Unnötig, denn du hast diese Zeichen eben gelöscht. 
    #    Effektiv prüfst du hier nur, ob word=="".
    #if word in string.punctuation or word in string.whitespace: #Leer- und Sonderzeichen abfangen
    #    return False

    # 4. Huch? Warum soll 121 kein Palindrom sein?
    #if word.isdigit() == True: #Zahlen abfangen, da z.B. 121 rueckwaerts auch 121 ergibt
    #    return False

    # 5. geht simpler mit reverse=word[::-1]
    #for i in range(len(word)-1, 0-1, -1): #Wort rueckwaerts zusammen basteln
    #    reverse = reverse + word[i]

    # zu 3 und 4: Wenn du unbedingt willst, kannst du die 
    # Spezialfälle auch hier aussondern:
    return ( word != '' # kein leeres Wort
         and not word.isdigit() # keine Zahlen
         and word[::-1].lower() == word.lower(): #Rueckwaerts-Wort mit vorwaerts-Wort vergleichen
           )
try:
    with open(file, 'r') as f:
        # 6. Warum willst du eine 100 TB große Textdatei 
        #    auf einmal lesen?
        #lines = f.readlines()

        # Eine einzelne Zeile ist doch mehr als genug.
        # Auch Zeilen können ziemlich lang sein, aber ich 
        # kenne keine Methode, einzelne Wörter zu lesen.
        for line in f:
            #Einzelne Woerter im Text der Funktion check_polindrome uebergeben
            # 7. split() ohne Argument trennt bei jeder 
            # Folge von Whitespace. Das reicht hier völlig. 
            # Außerdem musst Du dann beim Check keinen 
            # Whitespace mehr entfernen:
            for word in line.split():
                if check_polindrome(word):
                    polindrome.append(word)

except FileNotFoundError:
    print('File not found!')
    # 8. exit(0) hieße "alles in Ordnung".
    exit(1)