Nur eine bestimmte Anzahl an Zeichen strip()'en?

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
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Entweder übersehe ich etwas in der Dokumentation, oder ich ein Einzelfall.

Ich brauche eine Funktion, die genau wie die 'strip' Funktionen funktioniert. Also bestimmte Zeichen Links('lstrip'), Rechts('rstrip') bzw. an beiden Seiten abschneidet.

Ich habe das ganze als Funktion in http://trac.webshox.org/browser/globby/utils.py mal geschrieben (gaanz unten)

Gibt es so etwas schon in der Standardbibliothek? Mir gefällt nämlich meine Lösung überhaupt nicht :'(


MfG EnTeQuAk
BlackJack

Je nachdem ob `chars` angegeben wird oder nicht macht die Funktion etwas völlig anderes. Schlechter Entwurf würde ich mal sagen.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Je nachdem ob `chars` angegeben wird oder nicht macht die Funktion etwas völlig anderes. Schlechter Entwurf würde ich mal sagen.
Schlechter Entwurf, stimme ich dir zu. Aber --> Was ganz anderes? Wenn Chars gegeben ist, wird nur 'chars' angeschnitten, ansonsten werden die ganz normalen 'strip' Methoden angewandt. Mal schaun... vllt. schreibe ich auch einen kompletten Ersatz der 'strip' Methoden.

MfG EnTeQuAk
BlackJack

In einem Fall gibt man eine Anzahl vor, die bestimmt wieviel abgeschnitten wird, im anderen liegt es an den Zeichen selbst. Wenn eine Anzahl vorgeben wird, werden auch Zeichen entfernt, die sonst stehen bleiben würden. Das ist für mein Gefühl ein völlig anderes Verhalten.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Hallo EnTeQuAk

zu Beginn eine Frage, kann es sein das die Abfrage 'if chars' nicht wirklich gebraucht wird?!
EnTeQuAks link hat geschrieben:

Code: Alles auswählen

...
if chars:
    chars = (chars>0 and chars)
...
weiterhin schreibst du das du strip um ein feature erweiterst, entziehst dem User aber die Möglichkeit den strip-Funktionen wie gewohnt Parameter zu übergebn.

Ich kann dem BlackJack im Ansatz recht geben das es sich mitunter für den User etwas seltsam anfühlt, dass sich ja nach Parameter Typ die Rückgabe unterscheided.
Bin aber auch dem Charm erlegen das mal in eine Funktion zusammenzufassen ;)

Das ist dabei heraus gekommen.:

Code: Alles auswählen

def strip_ext(text, char=None, align="lr"):
    """strip_ext(text, char=None, align="lr") -> str\n\n
    Strip-function, extended with alignment ("l","r","lr")\n
    Also adding the functionality for stripping by number of chars
    """
    arglist = [ "l", "r", "lr"]
    assert align in arglist, "Unexpected argument '%s'!" % align 
    
    try:
        # first try our extended functionality strip by count
        ranges = dict( zip( arglist, [ ( char, None), 
                                       ( None, -char), 
                                       ( char, -char)]))
        start, end =  ranges[align] 
        return text[start:end]
    except:
        # When it fails go back to the standard strip functions
        stripfuncs = dict( zip( arglist, [ text.lstrip,
                                       text.rstrip,
                                       text.strip]))  
        return stripfuncs[align](char)
Die ersten Tests waren eigentlich recht vielversprechend.
Bin aber für Verbesserungen offen :)

Edit: Einige Fehler im code ausgemerzt. Nu sollte alles funktionieren :roll:
Zuletzt geändert von Zap am Mittwoch 16. Mai 2007, 06:51, insgesamt 2-mal geändert.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Sieht schonmal interessant aus.

Ich bin da einen komplett anderen Weg gegangen. Funktioniert nun auch wunderbar --> nur kann ich es hier nicht posten, da ich die Datei leider auf Arbeit habe und vergessen habe, sie mir zu schicken :mrgreen: :mrgreen: :twisted: :twisted: :lol:

Werde sie morgen aber zur Disskusion stellen ;)

MfG EnTeQuAK
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

So. Ich habe es nicht komplett getestet. Aber ich gehe mal davon aus, das es halbwegs einwandfrei läuft.

Ich bitte sehr um Vorschläge/Kritik. Bzw. Möglichkeiten, den Quelltext etwas zu verkürzen. Denn irgentwie kommt er mir sehr lang vor.

Code: Alles auswählen

def strip_ext(text, chars=None, num=None, align="b"):
    """
    strip_ext(s [,chars, num, align]) -> string

    Return a copy of the string s with leading and/or trailing
    whitespace removed.
    If chars is given and not None, remove characters in chars instead.
    If chars is unicode, S will be converted to unicode before stripping.
    If num is given and not None, remove max. num characters if given, whitespaces
    if not.
    """
    if chars is None:
        chars = ' '
    else:
        if isinstance(chars, unicode):
            text = to_unicode(text)

    arglist = [ "l", "r", "b"]
    assert align in arglist, "Unexpected argument '%s'!" % align
    if num:
        # we use the new feature, that we can strip max. 'n' 'chars'
        if align == 'l':
            result = [x for x in reversed(text)]
            for i, c in enumerate(text):
                if c in chars and i<num:
                    result.pop()
            result = ''.join(reversed(result))
        elif align == 'r':
            result = [x for x in text]
            for i, c in enumerate(reversed(text)):
                if c in chars and i<num:
                    result.pop()
            result = ''.join(result)
        else:
            # align == 'b'
            #it's easier to call strip_ext recursive
            r = strip_ext(text, chars, num, 'r')
            result = strip_ext(r, chars, num, 'l')
    else:
        import string
        funcs = {
            'l': string.lstrip,
            'r': string.rstrip,
            'b': string.strip,
        }
        result = funcs[align](text, chars)
    return result

if __name__ == '__main__':
    assert strip_ext('  dd laladidid', 'd ', 3, 'l') == 'd laladidid'
    assert strip_ext('llaaddd d i   ', 'di ', align='r') == 'llaa'
    assert strip_ext('llaaddd d i   ', 'di ', 4, 'r') == 'llaaddd d '
    assert strip_ext('   lala   ') == 'lala'
    assert strip_ext('   lalala   ', num=2, align='b') == ' lalala '
MfG EnTeQuAk
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Die Art, wie du den String zuerst umkehrst, in eine Liste konvertierst und dann wieder umdrehst, kommt mir etwas umständlich vor. Wie wärs mit

Code: Alles auswählen

i = 0
l = len(text)
while i < num and i < l and text[i] in chars:
    i += 1
result = text[i:]
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

birkenfeld hat geschrieben:Die Art, wie du den String zuerst umkehrst, in eine Liste konvertierst und dann wieder umdrehst, kommt mir etwas umständlich vor. Wie wärs mit

Code: Alles auswählen

i = 0
l = len(text)
while i < num and i < l and text[i] in chars:
    i += 1
result = text[i:]
Währe eine Möglichkeit. Jedoch muss ich den text, komme was wolle umdrehen. Mindestens einmal. Entweder bei rechts oder links ;)

Ich werde mal probieren, deine Lösung in die schöne Funktion zu migrieren. Mal schaun :)

MfG EnTeQuAk
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Das verstehe ich nicht...

Code: Alles auswählen

l = len(text)
i = l
while i > l-num and  i > 0 and text[i-1] in chars:
    i -= 1
result = test[:i]
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Antworten