Seite 1 von 1

RegEx: doppeltes Wort löschen

Verfasst: Donnerstag 6. März 2008, 23:34
von Raggi
Hallo,

wie kann man über einen regulären Ausdruck ein doppeltes Wort löschen? Auf diese Weise bekomme ich nur die doppelten angezeigt

Code: Alles auswählen

>>> p = re.compile(r'(?P<word>\b\w+)\s+(?P=word)')
>>> p.search('Paris in the the spring').group()
'the the'

Verfasst: Freitag 7. März 2008, 00:01
von audax
öhm...erstelle eine zweite Gruppe, die auf den Inhalt der ersten Gruppe matcht und ersetze diese dann durch nichts.

Code: Alles auswählen

In [30]: from re import X, M, S
In [31]: s
Out[31]: u'Ich bin bin K\xe4se!'

In [32]: re.sub(r"(?P<word>\b\w+)\s+(?P<double>(?P=word))", r'\1', s, X|M|S)
Out[32]: u'Ich bin K\xe4se!'
(Den Namen hab ich nur gegeben, ums klarer zu machen, der ist unnötig...)

Verfasst: Freitag 7. März 2008, 00:16
von Raggi
großartig! AUf die Idee kam ich gar nicht.
Funktioniert - besten Dank

Verfasst: Freitag 7. März 2008, 08:18
von jens
Also ich würde den import nicht so nutzten. Entweder re.X, re.M, re.S oder direkt in der RE hinterlegen, ich glaube das geht so: r"(?P<word>\b\w+)\s+(?P<double>(?P=word))(?xms)"

Verfasst: Freitag 7. März 2008, 12:14
von audax
Ah, danke!

Ich hab in der Doku nicht gefunden, wie es geht, muss es wohl überlesen haben...

Ich wollte mir für RegExp schon zusamen mit functool.partial nen ordentlich compile() mit den richtigen Flags in die Toolbox packen :D

Verfasst: Freitag 7. März 2008, 15:05
von Raggi
mein Wert sieht so aus:
1111*Risikotragung|1112*Garantie|1113*Verbraucherschutz:Warenkauf|1112*Garantie

mit dem Code von audax werden aber nur doppelte Wörter, die hintereinander stehen und mit Leerzeichen getrennt sind, gelöscht

Wisst Ihr, wie man doppelte Wörter in unbekannter Reihenfolge ohne Leerzeichen löscht?

Verfasst: Freitag 7. März 2008, 15:18
von keppla
Raggi hat geschrieben:Wisst Ihr, wie man doppelte Wörter in unbekannter Reihenfolge ohne Leerzeichen löscht?
Wild geraten, aber bekommst du nicht vielleicht das, was du willst, wenn du alle Wörter suchst, und die dann in ein Set schmeist, so dass du keine Doppelten mehr hast? Oder gehts dir auch um die Reihenfolge und die "nichtwörter" im Text?

Verfasst: Freitag 7. März 2008, 15:20
von BlackJack
@Raggi: Am besten nicht mit einem regulären Ausdruck. Falls die Reihenfolge der einzelnen Daten im Ergebnis egal ist:

Code: Alles auswählen

print '|'.join(set(data.split('|')))
Falls die Reihenfolge erhalten bleiben soll:

Code: Alles auswählen

def delete_doublettes(line, separator='|'):
    seen = set()
    result = list()
    for item in line.split(separator):
        if item not in seen:
            seen.add(item)
            result.append(item)
    return separator.join(result)

Verfasst: Freitag 7. März 2008, 15:32
von audax

Code: Alles auswählen

words = re.findall(r'(\w+)\s+(?xms)', foobar, re.UNICODE)
for word in words:
    how_often = len(re.findall(word, s))
    if how_often > 1:
        s = re.sub(word, '', s, how_often-1)
€dit:
Das '\s' ersetzt man dann natürlich durch seinen eigenen seperator.
Und das '\w' durch...naja, was auch immer man als Wort erkannt haben will.

Verfasst: Freitag 7. März 2008, 15:39
von Raggi
NameError: global name 'set' is not defined

"Set" wurde wohl in Python2.4 eingeführt.
Ich muss aber 2.3 nehmen

Gibt es noch einen anderen Weg?

Verfasst: Freitag 7. März 2008, 15:45
von Trundle
In Py-2.3 bekommt man das einfach mit

Code: Alles auswählen

from sets import Set as set

Verfasst: Freitag 7. März 2008, 15:47
von audax
Natürlich gibt es einen anderen Weg. Es gibt hunderte.

Code: Alles auswählen

splitted = data.split('|')
normalized = []
for token in splitted:
    if not token in normalized:
        normalized.append(token)
data = '|'.join(normalized)
Das sollte verständlich genug sein...

Verfasst: Freitag 7. März 2008, 17:56
von Raggi
Riesiges DANKE an Euch alle!

habe mich nun für

Code: Alles auswählen

print '|'.join(set(data.split('|')))
entschieden. Unglaublich, wie einfach Python ist, wenn man es kennt!