Seite 1 von 1

String kürzen

Verfasst: Donnerstag 3. Dezember 2009, 14:44
von mit
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

Verfasst: Donnerstag 3. Dezember 2009, 16:37
von 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!?

Verfasst: Donnerstag 3. Dezember 2009, 17:00
von /me
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.

Verfasst: Donnerstag 3. Dezember 2009, 17:15
von Defnull
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)   

Verfasst: Donnerstag 3. Dezember 2009, 17:20
von /me
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.

Verfasst: Freitag 4. Dezember 2009, 15:43
von mit
Vielen Dank.

Wie könnte man am besten Unit Test verwenden?

Verfasst: Freitag 4. Dezember 2009, 15:51
von Defnull
Ich empfehle, sie erst zu schreiben und dann aus zu führen, vorzugsweise mit einem Python Interpreter.

Verfasst: Samstag 5. Dezember 2009, 01:26
von mit
Wie schreibt man es am besten?

Verfasst: Samstag 5. Dezember 2009, 09:09
von snafu
mit hat geschrieben:Wie schreibt man es am besten?
Vorzugsweise mit Köpfchen. *scnr*

Verfasst: Samstag 5. Dezember 2009, 09:16
von 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.