Darell: str_replace wie verbessern?

Hallo,

ich bin durch Google auf dieses Forum aufmerksam geworden ( https://forum.selfhtml.org/self/2017/aug/21/php-teile-im-string-ersetzten/1702129#m1702129 ). Ich habe mir eine Art "Rechtschreibkorrektur" gebastelt, und versuche nun die Falschschreibweisen aus dem String zu korrigieren. Bisher nutze ich für das Ersetzten der Rechtschreibfehler str_replace, in den Tests funktionierte es zuerst zuverlässig. Bis ich bei längern Texten bemerkte das hier ggf. doppelungen (Schule/Schulen) zu problemen führen können. Ähnlich wie im oben verlinkten Beitrag kenne ich die Positon(im String)/Länge sowie das zu ersetztende Wort selbst. Str_replace ist hier zu grob um genau ein Wort im String zu ersetzten.

Die im Artikel verlinkte http://php.net/manual/de/ref.mbstring.php konnte mir keine Funktion liefern mit der ich anhand der Postion einen Stringteil setzen könnte.

Vielen Dank schon einmal im Voraus.

  1. Hallo Darell,

    Die im Artikel verlinkte http://php.net/manual/de/ref.mbstring.php konnte mir keine Funktion liefern mit der ich anhand der Postion einen Stringteil setzen könnte.

    Wenn du Position im String und Länge des Wortes kennst, kannst du mit substr() den String vor und nach dem Wort abschneiden und mit der verbesserten Version wieder zusammen setzen, etwa so (ungetestet, um das Prinzip zu verdeutlichen):

    $word_pos = 10;
    $word_len = 5;
    
    $str_before = substr($str, $word_pos, $word_len);
    $str_after = substr($str, $word_pos + $word_len);
    $str = $str_before . $new_word . $str_after;
    

    LG,
    CK

    1. Hi,

      Wenn du Position im String und Länge des Wortes kennst, kannst du mit substr() den String vor und nach dem Wort abschneiden und mit der verbesserten Version wieder zusammen setzen, etwa so (ungetestet, um das Prinzip zu verdeutlichen):

      
      > $word_pos = 10;
      > $word_len = 5;
      > 
      > $str_before = substr($str, $word_pos, $word_len);
      
      

      wohl eher

      $str_before = substr($str, 0, $word_pos);
      

      denn der Teil vor dem zu ersetzenden Wort fängt ja am Stringanfang an und endet an der Position des zu ersetzenden Wortes.

      
      > $str_after = substr($str, $word_pos + $word_len);
      > $str = $str_before . $new_word . $str_after;
      
      

      cu,
      Andreas a/k/a MudGuard

      1. Hallo MudGuard,

        wohl eher

        $str_before = substr($str, 0, $word_pos);
        

        denn der Teil vor dem zu ersetzenden Wort fängt ja am Stringanfang an und endet an der Position des zu ersetzenden Wortes.

        Autsch… 😂 ja, natürlich. Posten und Telko gleichzeitig geht wohl doch nicht sinnvoll, auch wenn man nicht aufpasst 😉

        LG,
        CK

        1. Vielen Dank euch beiden, hat wunderbar funktioniert...

    2. @@Christian Kruse

      Wenn du Position im String und Länge des Wortes kennst, kannst du mit substr() den String vor und nach dem Wort abschneiden

      String und substr() verträgt sich nicht.

      Alles, was nicht mit mb_ anfängt, sind keine String-Funktionen.

      LLAP 🖖

      --
      “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
      1. Hallo Gunnar,

        Wenn du Position im String und Länge des Wortes kennst, kannst du mit substr() den String vor und nach dem Wort abschneiden

        String und substr() verträgt sich nicht.

        Alles, was nicht mit mb_ anfängt, sind keine String-Funktionen.

        Ich habe hier mit bedacht substr() gewählt und nicht die Multibyte-Variante gewählt.

        Deine Aussage ist viel zu pauschal, als dass sie wahr oder richtig sein könnte. Gerade in diesem Zusammenhang höchstwahrscheinlich falsch. Der OP sprach von Rechtschreibprüfung, was die Vermutung nahelegt, dass er Byte-Offsets und -Länge bekommt: aspell, ispell und Konsorten geben dir die Byte-Offsets, nicht den Offset in Anzahl Codepoints.

        LG,
        CK

        1. @@Christian Kruse

          String und substr() verträgt sich nicht.

          Alles, was nicht mit mb_ anfängt, sind keine String-Funktionen.

          Deine Aussage ist viel zu pauschal, als dass sie wahr oder richtig sein könnte. Gerade in diesem Zusammenhang höchstwahrscheinlich falsch.

          Inwiefern?

          Ich habe hier mit bedacht substr() gewählt und nicht die Multibyte-Variante gewählt.

          Ja und? Dann hast du mit Bedacht eine Bytesequenz-Funktion gewählt und keine String-Funktion.

          LLAP 🖖

          --
          “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
          1. Hello,

            Ich habe hier mit bedacht substr() gewählt und nicht die Multibyte-Variante gewählt.

            Ja und? Dann hast du mit Bedacht eine Bytesequenz-Funktion gewählt und keine String-Funktion.

            ... was ja auch für den Vergleich von Bytesequenzen vollkommen ausreicht und wesentlich schneller ist, als die Multibyte-Stringfunktionen.

            Liebe Grüße
            Tom S.

            --
            Es gibt nichts Gutes, außer man tut es!
            Das Leben selbst ist der Sinn.
  2. Hello,

    wenn Du nicht nach "Schule", sondern nach " Schule " suchen lassen würdest, würde es in den meisten Fällen wieder funktionieren.

    Zum Thema Verbesserungen:
    Leider liefert str_replace() nur den Ergebnisstring, nicht aber eine Trefferliste, die z. B. die Position im alten Text oder fünf Zeichen links und fünf Zeichen rechts vom Treffer mit abspeichert. Die würdest Du aber vermutlich für eine anschließende Sichtkontrolle benötigen. So etwas könntest Du dir mit preg_match_all() bauen.

    Außerdem möchte ich Dir für Stringoperationen noch die Mutlibyte-Funktionen ans Herz legen und die Überlegung, wann diese notwendig werden, oder wann byteweiser Vergleich (immer noch) die richtige Variante ist.

    Liebe Grüße
    Tom S.

    --
    Es gibt nichts Gutes, außer man tut es!
    Das Leben selbst ist der Sinn.
  3. Hallo Darell,

    Fuzzy Matching könnte für Dich bei der Rechtschreibkorrektur interessant sein. Wenn Du sprachlich flexibel bist, das auf Python basierende regex Package (suche auf der Seite nach 'fuzzy') kann das. Beispiel:

    Problem

    Lösung:

    # pip install regex
    
    >>> import regex
    >>> pattern = regex.compile('(Honolulu|Hawaii){i<=2,d<=2,s<=2,e<=4}')
    >>> pattern.match('Honalulu')
    
    <regex.Match object; span=(0, 8), match='Honalulu', fuzzy_counts=(1, 0, 0)>
    
    >>> pattern.match('Honoloulou')
    
    <regex.Match object; span=(0, 10), match='Honoloulou', fuzzy_counts=(2, 2, 0)>
    
    >>> pattern.match('Hawaai')
    
    <regex.Match object; span=(0, 6), match='Hawaai', fuzzy_counts=(1, 0, 0)>
    
    >>> pattern.match('Fargo')
    >>> # Nichts gefunden
    
    

    Gruß, Nils

    1. Nachtag: Ich sehe gerade, PHP kann das auch:

      similar_text levenshtein

      Gruß, Nils

      1. Nachtrag:

        Nachtag

        Meinten Sie: 'Nachtrag'?

        Gruß, Nils

        1. Hallo Nils,

          Nachtrag:

          Nachtag

          Meinten Sie: 'Nachtrag'?

          Nur falls du es noch nicht wusstest: Man kann seine Beiträge 20 Minuten lang editieren, so lange noch niemand darauf geantwortet hat.

          Gruß
          Julius

          1. @@Julius

            Nur falls du es noch nicht wusstest: Man kann seine Beiträge 20 Minuten lang editieren, so lange noch niemand darauf geantwortet hat.

            Was bin ich froh, dass diese lästigen Einschränkungen für mich nicht mehr gelten. 😝

            LLAP 🖖

            --
            “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
            1. Hallo Gunnar,

              Nur falls du es noch nicht wusstest: Man kann seine Beiträge 20 Minuten lang editieren, so lange noch niemand darauf geantwortet hat.

              Was bin ich froh, dass diese lästigen Einschränkungen für mich nicht mehr gelten. 😝

              Moderatoren-Werkzeuge-Medaille?

              Gruß
              Julius

          2. Hallo Julius,

            Danke für den Tipp!

            Gruß, Nils