String kürzen

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
mit
User
Beiträge: 285
Registriert: Dienstag 16. September 2008, 10:00

Hallo,
ich habe diese Datei:

Code: Alles auswählen

SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS
BBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSQQQQQQQQQQQQQQQQS
SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSSPPPPQQQQQQRRRRRRSSSSSPPPQS
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
SPPPPQQQQQBBBBBBBBBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS
Ich habe folgenden Code der Strings kürzt, wenn diese A-0 beinhalten:

Code: Alles auswählen

#!/usr/bin/env python

def findBiggestLength(line):
    i = 0
    startPosFound = False
    startPos = 0
    endPos = 0
    biggestSeqLength = 0
    length = len(line)
    
    while i < length:
        if (line[i] >= MIN_QUALITY) and (startPosFound == False): 
                startPos = i
                startPosFound = True
        elif line[i] < MIN_QUALITY:
            biggestSeqLength = i - startPos + 1 
            if biggestSeqLength < MIN_TRIM:
                startPos = i
        else: 
            endPos = i         
        i += 1
    return (startPos, endPos+1)    


MIN_TRIM = 50-1
MIN_QUALITY = chr(15 + 64)

print MIN_QUALITY

trimmed = 0
deleted = 0

for line in open('test.txt','r'):
    if not line:
        break
    (startPos, endPos) = findBiggestLength(line)
    biggestSeqLength = endPos - startPos + 1 

    if biggestSeqLength < MIN_TRIM:
        deleted += 1
        continue
    trimmed_line = line[startPos:endPos]
    
    print trimmed_line, startPos, endPos, biggestSeqLength, "\n"

    trimmed += 1

print "trimmed: ", trimmed, "deleted: ", deleted 
Dieser Code liefert folgende Ausgabe:

Code: Alles auswählen

O
SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS 0 49 50 

SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS 10 59 50 

SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS 27 76 50 

SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSQQQQQQQQQQQQQQQQS 10 76 67 

SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSSPPPPQQQQQQRRRRRRSSSSSPPPQS 0 76 77 

BSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS 26 76 51 

trimmed:  6 deleted:  2
Leider wird die letzte Zeile falsch gekürzt und die Start Postion müsste 27 und nicht 26 sein damit B ausgeschnitten wird.

Warum werden alle Zeilen richtig gekürzt, aber nicht die letzte?

Viele Grüße
BlackJack

@mit: Versetz Dich mal bitte in die Lage von jemandem der nicht weiss was Du machst, und formuliere die Frage dann vielleicht noch einmal neu.

Ich sehe da nur einen Haufen Buchstaben als Eingabe, Code der da irgendwas mit macht, und eine Ausgabe deren Bedeutung oder Zusammenhang mit der Eingabe ich nicht verstehe.

Und der Code dazwischen ist mir auch zu komplex zum raten.

Vielleicht mal in Worten wie man von der Eingabe zur gewünschten Ausgabe kommt!?
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

BlackJack hat geschrieben:Ich sehe da nur einen Haufen Buchstaben als Eingabe, Code der da irgendwas mit macht, und eine Ausgabe deren Bedeutung oder Zusammenhang mit der Eingabe ich nicht verstehe.
Ich glaube die Daten werden zeilenweise eingelesen und dann soll pro Zeile die längste Sequenz ermittelt werden die keine Buchstaben von A (Ah) bis O (Oh) enthält.

Spontan ist mir da so etwas eingefallen (exemplarisch mit einer Beispielzeile und mit print aufgelockert)

Code: Alles auswählen

import re
    
strange_data = "SPPPPQQQQQBBBBBBBBBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS"

parts = re.split("[A-O]+", strange_data)
print(parts)

parts.sort(cmp=lambda x,y: cmp(len(y), len(x)))
print(parts)

laengste_sequenz = parts[0]
print(laengste_sequenz)
Ich weiß nicht genau, was da sonst noch an Prüfungen drin ist, aber das lässt sich hier sicher problemlos einbauen.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Ich würde es auch mit re machen, aber finditer() benutzen, wenn die Position des Strings noch gebraucht wird.

Beim sortieren ist 'key' übrigens performanter als 'cmp'.

Code: Alles auswählen

>>> import re
>>> line = 'SPPPPQQQQQBBBBBBBBBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS'
>>> mrex = re.compile(r'[^A-O]+')
>>> matches = mrex.finditer(line)
>>> top = sorted(matches, key=lambda m: len(m.group()))
>>> if top:
...     print top[-1].group(), top[-1].span()
... else:
...     print 'No match'
... 
SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS (27, 76)   
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Defnull hat geschrieben:Ich würde es auch mit re machen, aber finditer() benutzen, wenn die Position des Strings noch gebraucht wird.
Schick. finditer() habe ich noch nie verwendet und kannte es nicht.
mit
User
Beiträge: 285
Registriert: Dienstag 16. September 2008, 10:00

Vielen Dank.

Wie könnte man am besten Unit Test verwenden?
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Ich empfehle, sie erst zu schreiben und dann aus zu führen, vorzugsweise mit einem Python Interpreter.
Bottle: Micro Web Framework + Development Blog
mit
User
Beiträge: 285
Registriert: Dienstag 16. September 2008, 10:00

Wie schreibt man es am besten?
Benutzeravatar
snafu
User
Beiträge: 6881
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

mit hat geschrieben:Wie schreibt man es am besten?
Vorzugsweise mit Köpfchen. *scnr*
BlackJack

Und unter Zuhilfenahme von `nose` oder `py.test`, dann hat man weniger Schreibarbeit. Zum Beispiel (sollte mit beiden funktionieren):

Code: Alles auswählen

def test_find_biggest_length():
    data = [
 'SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSBBBBBBBBBBBBBBBBBBBBBBBBBBB',
 'BBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSBBBBBBBBBBBBBBBBB',
 'BBBBBBBBBBBBBBBBBBBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS',
 'BBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSQQQQQQQQQQQQQQQQS',
 'SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQSSPPPPQQQQQQRRRRRRSSSSSPPPQS',
 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB',
 'SPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB',
 'SPPPPQQQQQBBBBBBBBBBBBBBBBBSPPPPQQQQQQRRRRRRSSSSSPPPPPPRRRRRRRRRRRRQQQQQQQQS',
    ]

    
    expected = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
    
    def test(line, positions):
        assert positions == find_biggest_length(line)
    
    for line, positions in zip(data, expected):
        yield test, line, positions
Anstelle der ``(0, 0)`` müssen da natürlich die Zahlen stehen, die man tatsächlich erwartet. Ausserdem sollten in den Daten auch noch die diversen Randfälle stehen, wie zum Beispiel die leere Zeichenkette.
Antworten