Zahlen / Datum auslesen - Probleme mit eigener Funktion - Hilfe gesucht

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
yoxso
User
Beiträge: 2
Registriert: Mittwoch 27. Mai 2020, 18:24

Hallo zusammen,

ich versuche momentan eine Funktion zu erstellen, die alle Elemente (Strings) einer Liste nach Zahlenwerten durchsucht. Es geht letztendlich darum, mit einfachen Kriterien herauszufinden, ob die im String vorhandenen Zahlen (wenn überhaupt welche vorhanden) ein Datum sein können oder nicht. Mit datefinder geht das leider nicht, weil ich das deutsche Datumsformat brauche.

In meiner bisherigen Lösung hab ich jetzt das Problem, dass ich durch die ganzen Verschachtelungen die Variable deadline in der return-Anweisung nicht mehr aufrufen kann. Hat jemand eine Idee wie sich das beheben lässt?

Grundsätzlich reicht mir dieser "einfache" Ansatz, weil in der gesamten Liste nur ein richtiges Datum enthalten sein wird. Dieses gilt es eben herauszufiltern. Daher auch meine Idee nur Strings genauer anzuschauen, die 2 oder 3 Zahlenwerte enthalten.

Grundsätzlich sind immer wieder Probleme aufgetreten, wenn die Liste am Anfang die korrekten Datumswerte enthält und danach nur noch Elemente mit "falschen Voraussetzungen" kommen. Irgendwie fehlt glaube ich der Ausstieg aus der Schleife sofern das Datum erkannt wurde.

Vielleicht mach ich hier gerade auch nur triviale Anfängerfehler, aber mit meinen Grübeleien komme ich gerade einfach nicht weiter und hoffe, jemand kann mir ein paar Tipps geben. Wie man an meinem Code erkennen kann, ich arbeite noch nicht so lange mit Python :oops:

Code: Alles auswählen

def get_deadline(list):
    # Keywords to find the month if it has been written-out
    date_keywords = ["Januar", "Februar", "März", "April", "Mai","Juni",
    "Juli", "August", "September", "Oktober", "November", "Dezember"]

    # Find numbers in each string
    for str in list:
        digits = re.findall('([0-9]+)', str)
        if len(digits) <= 1 or len(digits) > 3:
            continue
        else:
            # Convert elements to make them comparable
            digits = [int(str) for str in digits]

            # Conditions to check if the numbers can be assumed as a date
            format_one = digits[0] >= 1 and digits[0] <= 31 and digits[1] >= 1 and digits[1] <= 12 and digits[2] >= 2010
            format_two = digits[0] >= 1 and digits[0] <= 31 and digits[1] >= 2010
            date_format = format_one or format_two

            # Ignore elements with wrong conditions
            if date_format == False:
                continue
            else:
                # Check the first possible date format
                if len(digits) == 3:
                    # Convert values into a datetime-object
                    deadline = datetime.datetime(digits[2],digits[1],digits[0],23,59,59)
                    # Check the second possible date format
                elif len(digits) == 2:
                    # Search for month in string and compare it to list of keywords
                    for month in date_keywords:
                        if re.search(month, str):
                            for i in range(1,12):
                                if month == date_keywords[i]:
                                    # Replace the value of month with a digit and convert values into a datetime-object
                                    new_month = i
                                    # Convert values into a datetime-object
                                    deadline = datetime.datetime(digits[1], new_month, digits[0],23,59,59)
                                    break
        return deadline 
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

`list` ist der Name eines eingebauten Typs und sollte nicht als Variablenname verwendet werden. Das gilt auch für `str`. `date_keywords` sind wohl eher `MONTHS` und sollten als Konstante am Anfang der Datei stehen. Alle `continue` sind überflüssig und sollten gelöscht werden.
Auf `False` prüft man mit `not date_format`.
`digits` sind keine Ziffern sondern Zahlen.
Die erste Prüfung funktioniert nur, wenn es wirklich 3 Zahlen gibt. Die spätere Umwandlung in ein Datum ist dann auch wieder davon abhängig, ob format_one oder format_two vorliegt, was Du aber ignorierst.
Einen konstanten String sollte man nicht per regulärem Ausdruck suchen, hier wäre der in-Operator ausreichend. Wenn Du einen Index brauchst, wäre der umständliche Weg über .index und nicht mit einer weiteren for-Schleife (wobei Listen mit Index 0 beginnen). Der richtige Weg ist mit enumerate.

Code: Alles auswählen

MONTHS = ["Januar", "Februar", "März", "April", "Mai","Juni",
    "Juli", "August", "September", "Oktober", "November", "Dezember"]

def get_deadline(sentences):
    # Find numbers in each string
    for sentence in sentences:
        numbers = re.findall('([0-9]+)', sentence)
        if 2 <= len(numbers) <= 3:
            # Convert elements to make them comparable
            numbers = [int(n) for n in numbers]

            # Conditions to check if the numbers can be assumed as a date
            if len(numbers) > 2 and 1 <= numbers[0] <= 31 and 1 <= numbers[1] <= 12 and numbers[2] >= 2010:
                return datetime.datetime(numbers[2], numbers[1], numbers[0], 23, 59, 59)
            elif 1 <= numbers[0] <= 31 and numbers[1] >= 2010:
                # Search for month in string and compare it to list of keywords
                for index, month in enumerate(MONTHS, 1):
                    if month in sentence:
                        return datetime.datetime(numbers[1], index, numbers[0], 23, 59, 59)
    raise RuntimeError("kein Datum gefunden")
yoxso
User
Beiträge: 2
Registriert: Mittwoch 27. Mai 2020, 18:24

Wow, vielen Dank, das hilft mir wirklich sehr!! Vor allem die vielen Hinweise.
Hab wohl noch einen langen Weg vor mir :lol:
Antworten