Zeilenumbruchsprüfung in Fließtext

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
DaFe4U
User
Beiträge: 9
Registriert: Freitag 16. April 2004, 22:05

Hallo zusammen,

ich habe folgendes kleines Problem...

Ein Fließtext soll alle 60 Zeichen umgebrochen werden. Grundsätzlich kein Problem. Ich würde nun aber gerne prüfen, ob an der Stelle 60 ein Umbruch "sinnvoll" möglich ist, sprich nicht mitten im Wort getrennt wird. Mein bisheriger Ansatz sieht vor, zu prüfen, ob das 60. Zeichen ein Leerzeichen ist. Wenn dies nicht der Fall ist, prüfe ich das 59. usw. bis ich ein Leerzeichen finde und setze an dieser Stelle ein "\n" ein. Meine Frage ist nun, ob jemandem eine etwas elegantere Lösung einfällt..?

Vielen Dank für Eure Hilfe!
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich würde das konstruktiv lösen: Starte mit einer leeren Zeile, füge dann so lange (durch Leerzeichen getrennte) Wörter zu einer Zeile hinzu, wie es passt. Andernfalls füge das Wort zur nächsten Zeile hinzu. Das kann dann so aussehen:

Code: Alles auswählen

s = r'Ein Fließtext soll alle 60 Zeichen umgebrochen werden. Grundsätzlich kein Problem. Ich würde nun aber gerne prüfen, ob an der Stelle 60 ein Umbruch "sinnvoll" möglich ist, sprich nicht mitten im Wort getrennt wird. Mein bisheriger Ansatz sieht vor, zu prüfen, ob das 60. Zeichen ein Leerzeichen ist. Wenn dies nicht der Fall ist, prüfe ich das 59. usw. bis ich ein Leerzeichen finde und setze an dieser Stelle ein "\n" ein. Meine Frage ist nun, ob jemandem eine etwas elegantere Lösung einfällt..?'

import re

def wrap(s, w=60):
    lines = []
    line1 = ""
    for word in re.findall(r"\S+", s):
        line2 = line1 + " " + word if line1 else word
        if len(line2) > w:
            lines.append(line1)
            line1 = word
        else:
            line1 = line2
    lines.append(line1)
    return "\n".join(lines)
    
print(wrap(s, 30))
Mein Algorithmus berücksichtigt nicht den Randfall, dass ein Wort breiter ist als die maximale Breite. Das überlasse ich dem Leser.

Stefan
BlackJack

@DaFe4U: Das `textwrap`-Modul in der Standardbibliothek ist bekannt!?

Edit:

Code: Alles auswählen

In [62]: print textwrap.fill(s, 60)
Ein Fließtext soll alle 60 Zeichen umgebrochen werden.
Grundsätzlich kein Problem. Ich würde nun aber gerne prüfen,
ob an der Stelle 60 ein Umbruch "sinnvoll" möglich ist,
sprich nicht mitten im Wort getrennt wird. Mein bisheriger
Ansatz sieht vor, zu prüfen, ob das 60. Zeichen ein
Leerzeichen ist. Wenn dies nicht der Fall ist, prüfe ich das
59. usw. bis ich ein Leerzeichen finde und setze an dieser
Stelle ein "\n" ein. Meine Frage ist nun, ob jemandem eine
etwas elegantere Lösung einfällt..?

In [63]: print textwrap.fill(s, 30)
Ein Fließtext soll alle 60
Zeichen umgebrochen werden.
Grundsätzlich kein Problem.
Ich würde nun aber gerne
prüfen, ob an der Stelle 60
ein Umbruch "sinnvoll" möglich
ist, sprich nicht mitten im
Wort getrennt wird. Mein
bisheriger Ansatz sieht vor,
zu prüfen, ob das 60. Zeichen
ein Leerzeichen ist. Wenn dies
nicht der Fall ist, prüfe ich
das 59. usw. bis ich ein
Leerzeichen finde und setze an
dieser Stelle ein "\n" ein.
Meine Frage ist nun, ob
jemandem eine etwas elegantere
Lösung einfällt..?
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

sma hat geschrieben:Mein Algorithmus berücksichtigt nicht den Randfall, dass ein Wort breiter ist als die maximale Breite. Das überlasse ich dem Leser.
Dem schließe ich mich mal an und komme unter der Prämisse dann zu einer sehr übersichtlichen Lösung:

Code: Alles auswählen

def wrap(s, w=60):
    lines = re.findall('(.{0,' + str(w) + '})(?:\\s|\\Z)', s)
    return "\n".join(lines)
Edit: Angepasst aufgrund des Hinweises von sma.
Zuletzt geändert von /me am Montag 25. Oktober 2010, 11:49, insgesamt 1-mal geändert.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Nett! Aber du verschluckst das letzte Wort. Benutze "(?:\\s|\\Z)" statt "\\s", dann klappt's.

Stefan
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Dafür gibt es ein Modul..Textwrap

//Edit: :oops: ich hab BlackJacks Post übersehen
the more they change the more they stay the same
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ReportLab hat diverse Funktion zum Textumbruch, von dumm bis intelligent, von Lateinischer Schrift (wie z.B. Deutsch) bis Japanisch.

Ob man das hier braucht weiß ich nicht. ;-)

Gruß, noisefloor
Antworten