Seite 1 von 1

Mustererkennung innerhalb eines String-Objektes

Verfasst: Dienstag 4. Februar 2014, 12:43
von uweddf
Hallo,

ich habe ein String-Objekt.
In diesem String kommen nur die Zeichen '+' oder '-' vor, also niemals andere.
Das String-Objekt selber hat keine feste Länge.
Mein Ziel ist es, innerhalb des String-Objektes nach bestimmten Mustern zu suchen und diese dann zu zählen bzw. zu ersetzen.

Mir ist durchaus bewusst, dass count() in meinem Fall nicht zum gewünschten Ergebnis führen kann, da diese Funktion
Zeichenweise vorgeht und somit zum Beispiel die Zeichenkombination '+-+-+' nicht als zwei Treffer erkennt.
Erkannt werden : 1x '+-+' und '-+' bleibt dann zum weiterzählen übrig.
Sorry, auch wenn das, was ich als Ergebnis haben möchte, sehr einfach umsetzbar wäre, ist mir kein brauchbarer
Lösungsansatz hierzu eingefallen. Für ein wenig Hilfe wäre ich daher sehr dankbar.

Ich hätte da auch noch ein zweites Problem mit der Funktion replace(), welches ähnlich gelagert ist.
Sollte die Lösung von dem Problem count() nicht adaptierbar auf replace() sein, bitte ich auch hier um ein wenig Hilfe.

Vielen Dank.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# String = '++-+++-++++---++++-+++--+-+-+-++++++-+-+++'
# Muster = '+-+'
# Gewünschtes Ergebnis : '++-+++-++++---++++-+++--+-+-+-++++++-+-+++'
# ..........................|...|...........|......|.|.|......|.|...
# ..........................1...2...........3......4.5.6......7.8...

# Versuch mit count()
a = '++-+++-++++---++++-+++--+-+-+-++++++-+-+++'

e = a.count('+-+')  # Ergebnis : e = 6 und das ist leider != 8


# Versuch mit replace()
b = a.replace('+-+', 'x-x')

# Ergebnis : b = '+x-x+x-x+++---+++x-x++--x-x-x-x++++x-x-+++'
# gewollt  : b = '+x-x+x-x+++---+++x-x++--x-x-x-x++++x-x-x++'
# .......................................................|



Re: Mustererkennung innerhalb eines String-Objektes

Verfasst: Dienstag 4. Februar 2014, 12:58
von BlackJack
@uweddf: Das zählen von überlappenden Treffern muss man selbst programmieren, aber das ist nicht weiter schwer:

Code: Alles auswählen

def count_overlapping(needle, haystack):
    result = 0
    index = -1
    while True:
        try:
            index = haystack.index(needle, index + 1)
            result += 1
        except ValueError:
            return result

Code: Alles auswählen

In [4]: count_overlapping('+-+', s)

Out[4]: 8
Das ersetzen ist ein wenig komplizierter. Aber auch machbar. Erster Schritt wäre aus der `count_overlapping()`-Funktion das finden der Indizes heraus zu ziehen würde ich sagen. Allerdings sind da auch Fragen offen denn das Beispiel reicht nicht wirklich als Spezifikation weil der Ersetzungsstring vom Muster her dem Suchstring entspricht. Darum macht es keinen Unterschied in welcher Reihenfolge man die Ersetzung vornimmt. Das muss ja aber nicht so sein.

Re: Mustererkennung innerhalb eines String-Objektes

Verfasst: Dienstag 4. Februar 2014, 13:12
von uweddf
@BlackJack: Vielen Dank für Deine schnelle Antwort.
Ich werde zuerst einmal die Funktion count_overlapping() versuchen zu verstehen und mit dem so hinzu gewonnen Wissen,
mein replace Problem versuchen zu lösen. Sollte dieses nicht funktionieren, werde ich mich noch einmal melden.

- Danke -

Re: Mustererkennung innerhalb eines String-Objektes

Verfasst: Dienstag 4. Februar 2014, 13:38
von Sirius3
Mit regulären Ausdrücken einfach zu lösen:

Code: Alles auswählen

def count_overlapping(pattern, string):
    return len(re.findall('(?=%s)'%re.escape(pattern), string)

def replace_overlapping(pattern, repl, string):
    return re.sub('([^x]{,%i})x'%len(pattern), lambda u:repl[-len(u.group(1)):], re.sub('(?<=%s)'%re.escape(pattern), 'x', x))

Re: Mustererkennung innerhalb eines String-Objektes

Verfasst: Dienstag 4. Februar 2014, 14:08
von uweddf
@Sirius3: Hallo Sirius3, vielen Dank für Deine fertige Lösung.

Ich hatte es bereits befürchtet, das mich dieses re Modul noch einmal quälen möchte.

Ich werde mich mit Deinem Lösungsvorschlag am Wochenende noch einmal auseinandersetzen um genau zu verstehen,
was die beiden Funktionen eigentlich wie tun.

Das einzig sinnvolle was ich bis jetzt mit dem re Modul zustande gebracht habe ist :
replace_pattern = re.compile('\t| |\n')

Selbst so triviale Ausdrücke wie: [a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*` lassen mich zur Zeit noch
leicht verzweifeln.

Vielen Dank,
für Deine beiden Lösungsvorschläge.