beste strategie für ein multiple string replace?



  • Was spricht gegen die ganz naive Variante?

    Du implementierst eine rekursive Funktion replace(str, patternIndex, patterns, replacements).

    Diese sucht das erste Vorkommnis von patterns[patternIndex]. Wenn es gefunden wurde, dann ist das Ergebnis

    replace(substringVorDemMatch, patternIndex + 1, patterns, replacements)
        + replacements[patternIndex]
        + replace(substringNachDemMatch, patternIndex, patterns, replacements)
    

    Und wenn nichts gefunden wurde, dann ist das Ergebnis einfach

    replace(str, patternIndex + 1, patterns, replacements)
    

    Abbruchbedingung fehlt dann natürlich noch, die ist natürlich einfach wenn patternIndex >= patterns.size() dann ist das Ergebnis einfach str.


    Das ganze kannst du dann noch schön umbauen so dass du keine Strings zurückgeben und konkatenieren musst - einfach einen Puffer (z.B. std::string oder std::vector<char>) als Parameter (by reference) übergeben wo die Funktion ihren Teil anhängt. Dadurch sollte die Sache ordentlich schneller werden.
    Und den 2. rekursiven Aufruf kann man noch einfach wegmachen indem man den Teil in eine Schleife umwandelt. Was günstig wäre, weil andernfalls die Rekursionstiefe auf sehr direkte Art und Weise vom Input-String abhängig wäre. D.h. man könnte sehr einfach nen Stack-Overflow produzieren.



  • @Bushmaster sagte in beste strategie für ein multiple string replace?:

    das ist nicht schön, oder?

    Ist die Frage ernst gemeint?

    @wob sagte in beste strategie für ein multiple string replace?:

    => Du musst also wissen, was du willst.



  • @Jockelx sagte in beste strategie für ein multiple string replace?:

    @Bushmaster sagte in beste strategie für ein multiple string replace?:

    das ist nicht schön, oder?

    Ist die Frage ernst gemeint?

    @wob sagte in beste strategie für ein multiple string replace?:

    => Du musst also wissen, was du willst.

    doch, denn ich will die ersetzungen optimieren, daher ist die entscheidung zuerst nach den längsten mustern zu suchen offenbar falsch.

    oder anders ausgedrückt: ist es besser in 'abcdef' ab, cd und ef zu finden, (3 ersetzungen) oder 'abc', was die ersetzung von 'cd' verhindert?



  • @hustbaer sagte in beste strategie für ein multiple string replace?:

    Was spricht gegen die ganz naive Variante?

    Du implementierst eine rekursive Funktion replace(str, patternIndex, patterns, replacements).

    Diese sucht das erste Vorkommnis von patterns[patternIndex]. Wenn es gefunden wurde, dann ist das Ergebnis

    replace(substringVorDemMatch, patternIndex + 1, patterns, replacements)
        + replacements[patternIndex]
        + replace(substringNachDemMatch, patternIndex, patterns, replacements)
    

    Und wenn nichts gefunden wurde, dann ist das Ergebnis einfach

    replace(str, patternIndex + 1, patterns, replacements)
    

    Abbruchbedingung fehlt dann natürlich noch, die ist natürlich einfach wenn patternIndex >= patterns.size() dann ist das Ergebnis einfach str.


    Das ganze kannst du dann noch schön umbauen so dass du keine Strings zurückgeben und konkatenieren musst - einfach einen Puffer (z.B. std::string oder std::vector<char>) als Parameter (by reference) übergeben wo die Funktion ihren Teil anhängt. Dadurch sollte die Sache ordentlich schneller werden.
    Und den 2. rekursiven Aufruf kann man noch einfach wegmachen indem man den Teil in eine Schleife umwandelt. Was günstig wäre, weil andernfalls die Rekursionstiefe auf sehr direkte Art und Weise vom Input-String abhängig wäre. D.h. man könnte sehr einfach nen Stack-Overflow produzieren.

    danke, aber wenn ich das richtig verstanden habe, finden folge-ersetzungen auf dem neu generierten string statt (rekursion). das soll ja gerade nicht sein.



  • @Bushmaster sagte in beste strategie für ein multiple string replace?:

    oder anders ausgedrückt: ist es besser in 'abcdef' ab, cd und ef zu finden, (3 ersetzungen) oder 'abc', was die ersetzung von 'cd' verhindert?

    Ist das ernst gemeint? Wie soll man das beantworten? Das hängt doch davon ab, was du erreichen willst!



  • @Bushmaster
    Nein, das hast du nicht richtig verstanden.

    Keys:
    	0: "aba"->"W"
    	1: "ba"->"T"
    	2: "bW"->"FAIL"
    Word: "xbabay"
    

    Aufruf: replace("xbabay", 0, keys, replacements). Das sucht jetzt erstmal nach keys[0], also "aba". Findet es an Offset 2.
    ->

    return	replace(str.substr(0, 2), 1, keys, replacements) // substr(0, 2) = Substring vor dem Match = "xb"
    	+ replacements[0] // replacements[0] = Replacement für den Match = "W"
    	+ replace(str.substr(5), 0, keys, replacements); // substr(5) = Substring nach dem Match = "y"
    

    Ein rekursiver Aufruf von replace bekommt also "xb" gefüttert und einer bekommt "y". D.h. da wird nicht nochmal was replaced da kein Match mehr gefunden wird. Ergebnis ist also "xbWy". "bW" wird nicht als Pattern erkannt und replaced, da der Teil vor einer Ersetzung, die Ersetzung selbst und der Teil nach der Ersetzung getrennt weiterverarbeitet werden. Und die Ersetzung selbst wird natürlich direkt 1:1 kopiert, darauf nochmal replace aufzurufen macht ja wenig Sinn.



  • @Bushmaster Welche Semantik/welches Regelwerk mehr Sinn macht musst schon du wissen, das ist ja wohl abhängig davon was du damit machen willst. Und wenn du das mal weisst, dann kann man sich überlegen wie man es möglichst elegant und/oder performant implementieren kann.

    Oder suchst du bloss etwas was möglichst performant zu implementieren ist und kannst mit allen Regeln leben die sich "daraus ergeben, hauptsache schnell"?

    Oder anders gesagt: du fragst was ist das beste? ... Erm... das beste wofür?



  • Ich frage mich hier auch, was der echte Anwendungsfall hierbei ist?
    Nur ein theoretischer, sonst wären die Regeln für das Ersetzen doch sicherlich vorgegeben (bzw. bekannt)?



  • @Th69 sagte in beste strategie für ein multiple string replace?:

    Ich frage mich hier auch, was der echte Anwendungsfall hierbei ist?
    Nur ein theoretischer, sonst wären die Regeln für das Ersetzen doch sicherlich vorgegeben (bzw. bekannt)?

    ja, es ist nichts vorgegeben. ich versuche die 'beste' multiple stringersetzung zu finden, wobei ich mir über 'beste' noch nicht im klaren bin.

    vielleicht ist es gut, verschiedene algorithmen anzuwenden und dann zu entscheiden, welcher davon die meisten teilstrings gefunden hat, und welcher davon die meisten zeichen ersetzen konnte. beispiel:

    gegeben ist: "abcdefgh"
    ersetzungen: "bcdefg->T", "ab->S", "cd->U".

    in einem fall könnte "aTgh" entstehen: 1 ersetzung, 6 Zeichen
    im anderen fall: "SUefgh" 2 ersetzungen, 4 zeichen

    was wäre besser? sollte man die anzahl der treffer maximieren, oder die anzahl ersetzter zeichen? oder gar die länge des endresultats?



  • @Bushmaster Wenn du keinen Anwendungsfall hast, dann ist es IMO total sinnfrei sich grossartig Gedanken darüber zu machen was denn das "beste" Regelwerk zum Ersetzen von mehreren Patterns/Substrings wäre.

    Das ist irgendwie wie sich zu überlegen was denn das "beste" Instrument ist, wenn man nicht weiss welche Musik man damit machen möchte, wie viele Arme/Beine der Spieler hat und ob man überhaupt Musik mag.


Log in to reply