Ankündigung

Einklappen
Keine Ankündigung bisher.

Suchfunktion für ß oder ss

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Suchfunktion für ß oder ss

    Hallo,

    ich habe für eine Webseite eine Suchfunktion gemacht, die 14 csv-Dateien vor allem nach Gemüsen und anderen Esswaren durchsuchtdurchsucht.
    Das klappt im Großen und Ganzen recht gut.
    Zur Sicherheit habe ich mir eine kleine Funktion eingebaut, die alle nicht gefundenen Suchbegriffe in eine Datei schreibt, die ich ab und an kontrolliere, um die Suchfunktion anzupassen, hauptsächlich, um Dinge trotz Schreibfehlern auffindbar zu machen.
    Auch das klappt im Großen und Ganzen recht gut, aber es gibt einen Ausreißer, den ich nicht in den Griff bekomme: "ss" und "ß".
    Dieser Rechtschreibfehler wird verblüffend oft gemacht.
    Ich würde gerne Süsskartoffel und Süßkartoffel finden oder Haselnuss und Haselnuß.

    Bisher versuche ich diese Probleme so zu lösen:

    if(($such == "möhre")|($such == "möhrchen")|($such == "möhren")|($such == "karotte")|($such == "karotten")|($such == "mohrrübe")){$such = "Gelbe Rübe";}
    if(preg_match("/moz/",$such)){$such = "mozzarella";}

    Hat mir jemand eine gute Idee?
    Ach ja, eine Datenbank gibt es leider nicht.

    Gruß, Hago

  • #2
    Zitat von hago Beitrag anzeigen
    Ach ja, eine Datenbank gibt es leider nicht.
    Dann solltest du das ändern. Genauo für sowas ist nämlich eine Datenbank erfunden worden.

    Kommentar


    • #3
      Vom Grundprinuzip her ist das schon richtig was du machst. Die meisten Suchen funktionieren nach dem Prinzip das Suchbegriff und die zu durchsuchenden Daten auf "einen nenner" gebracht werden.

      Z.B. wenn du aus allen ß ein ss machst und aus allen ss ein s. Spielt es keine Rolle ob nach Haselnuss, Haselnuß, oder Haselnus gesucht wird. So eine Normalisierung muss auf die zu durchsuchenden Daten und die Suchbegriffe angewendet werden.
      Was auch übelich ist, bei solchen Kategorien, alles zu singular umwandeln, was aber im Deutschen nicht ganz so einfach ist.
      Oder wenn es ganz "unscharf" sein soll, kannst du auch sowas wie php.net/metaphone verwenden. Das macht daraus eine Art Lautschrift. Das hat bei mir mit Vornamen/Nachnamen sehr gut funktioniert.
      Auch eine Suche nach Synonymen funktioniert nach dem Prinzip. Das wird dann aber nur auf einer Seite angewendet. Entweder suchst du dann pro Synom einmal und fügst die Treffer zusammen, oder du speicherst die Synonyme in den durchsuchenden Daten. Das hat beides Vor- und Nachteile.

      Ganz naiver Ansatz:

      PHP-Code:
      function normalizeValue(string $value): string
      {
          
      $value trim($value);
          
      $value mb_strtolower($value);
          
      $value str_replace('ß''ss'$value);
          
      $value str_replace('ä''ae'$value);
          
      $value str_replace('ö''oe'$value);
          
      $value str_replace('ü''ue'$value);
          
      $value preg_replace('~([a-z]){2,}~iu''\\1'$value); //jeden buchstaben löschen der doppelt mehrfach hintereinader kommt / achtung ist nicht getestet

          
      return $value;
      }

      function 
      getSynonyms(string $word): array
      {
          static 
      $map = [
              [
      'Karotte''Möhre''Mohrrübe''gelbe Rüben''Gelbrübe'],
              [
      'Kartoffel''Erdapfel'],
              ...
          ]

          foreach (
      $map as $words) {
              if (
      in_array($word$words)) {
                  return 
      $words
              
      }
          }

          return [
      $word];
      }


      $search_phrase 'Äpfel';

      $search_pharse_normalized normalizeValue($value);

      $csv = new SplFileObject('datei.csv');
      $csv->setFlags(SplFileObject::READ_CSV);
      foreach (
      $csv as $row) {
          
      //spalte 2 der csv durchsuchen
          
      $words getSynonyms($row[1]);

          foreach (
      $words as $word) {
              if (
      normalizeValue($word) === $search_pharse_normalized) {
                 echo 
      'Treffer in Datensatz';
                 
      var_dump($row);
              }
          }

      Aufwendig wirds wenn der Suchbegriff aus mehrere Wörtern bestehen kann und auch die zu durchsuchenden Daten.

      Auch wenn das für dich vielleicht keine Option ist. Eine Datenbanken wie z.B. elasticsearch oder solr nehmen dir dieses Thema weitgehenst ab. Das sind Datenbanken dir auf Suchen spezialisiert sind. Eine "normale"/ relationale Datenbank bringt in der Regel für diese Probleme auch keine sinnvolle Lösung mit.

      Kommentar


      • #4
        Zitat von hago Beitrag anzeigen
        Ach ja, eine Datenbank gibt es leider nicht.
        Warum nicht? SQlite ist standardmässig bei PHP dabei und würde dein Problem vereinfachen und du könntest auf die CSV-Dateien ganz verzichten.






        Kommentar


        • #5
          Zitat von erc Beitrag anzeigen
          So eine Normalisierung muss auf die zu durchsuchenden Daten ... ... angewendet werden.
          Das ist es vielleicht!
          Ich habe bisher immer nur versucht, den Suchbegriff anzupassen, vielleicht muss ich einfach die Daten "normalisieren" bevor ich sie durchsuche.

          Danke!

          Kommentar


          • #6
            Diese Methode hab ich mal irgendwo im Netz (auf SO?) gefunden...
            PHP-Code:
            private function normalizeString($str) {    
                static 
            $normalizeChars = array(        
                    
            'Š'=>'S''š'=>'s''Ð'=>'Dj','Ž'=>'Z''ž'=>'z''À'=>'A''Á'=>'A''Â'=>'A''Ã'=>'A''Ä'=>'A',        
                    
            'Å'=>'A''Æ'=>'A''Ç'=>'C''È'=>'E''É'=>'E''Ê'=>'E''Ë'=>'E''Ì'=>'I''Í'=>'I''Î'=>'I',        
                    
            'Ï'=>'I''Ñ'=>'N''Ń'=>'N''Ò'=>'O''Ó'=>'O''Ô'=>'O''Õ'=>'O''Ö'=>'O''Ø'=>'O''Ù'=>'U''Ú'=>'U',        
                    
            'Û'=>'U''Ü'=>'U''Ý'=>'Y''Þ'=>'B''ß'=>'Ss','à'=>'a''á'=>'a''â'=>'a''ã'=>'a''ä'=>'a',        
                    
            'å'=>'a''æ'=>'a''ç'=>'c''è'=>'e''é'=>'e''ê'=>'e''ë'=>'e''ì'=>'i''í'=>'i''î'=>'i',        
                    
            'ï'=>'i''ð'=>'o''ñ'=>'n''ń'=>'n''ò'=>'o''ó'=>'o''ô'=>'o''õ'=>'o''ö'=>'o''ø'=>'o''ù'=>'u',        
                    
            'ú'=>'u''û'=>'u''ü'=>'u''ý'=>'y''ý'=>'y''þ'=>'b''ÿ'=>'y''ƒ'=>'f',        
                    
            'ă'=>'a''î'=>'i''â'=>'a''ș'=>'s''ț'=>'t''Ă'=>'A''Î'=>'I''Â'=>'A''Ș'=>'S''Ț'=>'T',     
                );      
                return 
            strtr($str$normalizeChars);

            Macht jetzt nicht ganz genau, was dort oben gemacht wird (Ä => Ae usw.) aber das kann man ja noch anpassen. Aber sie deckt auch andere Sprachen ab, nicht nur Deutsch.
            Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

            Kommentar


            • #7
              PHP-Code:
              echo iconv('UTF-8''ASCII//TRANSLIT''ŠšŽžÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑŃÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïñńòóôõöøùúûüýýÿăîâșțĂÎÂȘȚ');
              // SsZzAAAAAAAECEEEEIIIINNOOOOOOEUUUUYssaaaaaaaeceeeeiiiinnooooooeuuuuyyyaiastAIAST 

              Kommentar


              • #8
                Ja, die iconv Variante sieht auch gut aus und schön kurz, ist aber mit Vorsicht zu genießen, da TRANSLIT abhängig von der Implementation ist (aka: abhängig vom OS).
                Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                Kommentar

                Lädt...
                X