koerschgen2001: Suchfunktion

hab mir eine kleine suchfunktion in javascript zusammengebastetl,naja den anfag.
es fehlen natürlich noch einige sachen(z.b. leerzeichen wegschneiden usw.)

Aber bevor ich weitermache wollte ich erstmall das jetzige problem lösen.

also wenn ich die suche starte zeigtd der mir danach ewig in der Statusleiste "den
pfad der datei" wird geöffnet an.
naja und ich hätte gerne das nach wenn man die suche nochmal startet der bildschirm
wiedergelöscht wird was jetzt nicht der fall ist, da wird alles untereinander geschrieben.

sagt mal was zu dem ansatz. geht , geht gar nicht, weg damit...?

also das array soll meinen stichwortindex darstellen, die wörter sind jetzt nur beispielwörter.

<html>
<head>
<title>Suchefunktion</title>
</head>
<body>
<form name="Suche">
<input type="text" name="Begriff">
<input type="submit" onClick="Suchfunktion()">
</form>
<script type="text/javascript">
<!--
function Suchfunktion()
{
text = new Array("meer","meeres","meeresgrund","meeresgrundleuchten");
var Begriff = document.Suche.Begriff.value;
for(i=0;i<=text.length;i++) {

for(j=0;j<=text[i].length;j++) {

for(k=1;k<=text[i].length;k++) {

var Extrakt = text[i].slice(j,k);

if(Begriff == Extrakt) {

//Suchwort fett hervorheben

l = j - j;
            for(l=l;l<j;l++) {
                var teil_1 = text[i].charAt(l);
                parent.Ergebnis.document.write(teil_1);
            }
            parent.Ergebnis.document.write("<b>"+Extrakt+"</b>");

for(m=k;m<text[i].length;m++) {
                var teil_2 = text[i].charAt(m);
                parent.Ergebnis.document.write(teil_2);
            }
            parent.Ergebnis.document.write("<br>");
        }

}
    }
}

}

//-->
</script>
</body>
</html>

P.S. Die Suchfunktion ist für einen Offlineinhalt, deshalb kann ich kein PHP benutzen.

  1. Hi,

    sagt mal was zu dem ansatz. geht , geht gar nicht, weg damit...?

    Von der grundsätzlichen Idee, aber wirklich nur ganz grundsätzlich ist es in Ordnung. Den Code kannst Du aber fast komplett entsorgen. Nur das Formular und das sortierte(?) Array ist benutzbar.

    also das array soll meinen stichwortindex darstellen, die wörter sind jetzt nur beispielwörter.

    Aber der Index ist sortiert? Wie groß wird denn der Index? Schon größer als nur einige zig Stück, oder?
    Dann wäre eine einfach binäre Suche anzuraten (bevor jemand Palaver macht: das reicht, soviele _können_ das gar nicht werden, das sich etwas komplexeres lohnen würde. So große Dateien läd kaum ein Browser.):

    function binarySearch( needle, haystack){
      var low    = 0;
      var high   = haystack.length - 1;
      var middle = 0;
      var round  = 0;
      while(low <= high){
        round++;
        middle = Math.floor((low + high)/2);
        if(needle < haystack[middle])
          high = middle - 1;
        else if (needle > haystack[middle])
          low = middle + 1;
        else
           return middle;
      }
      return -1;
    }

    Diese Funktion setzt aber voraus, das nicht nach lokal-lexikalischen Gesetzen sortiert wurde, sondern nach Buchstabenwerten und das alle Zeichensätze gleich sind.
    Also z.B. _nicht_:
    (latin-15)arm,ärmer,zulu
    sondern:
    (latin-15)arm,zulu,ärmer

    Was hattest Du noch? Ach ja: wenn Du die Ausgabe in einpackst, z.B. in ein div o.ä., dann kannst Du die ganze Box löschen. Das geht z.b. auch gut in Verbindung mit "reset" vom Formular.

    Beispiel:

    Am Anfang einfach sowas da hinschreiben, wo es auftauchen soll:
    [...]
    <div id="ausgabe"></div>
    [...]

    Eine Ausgabe dort erzielst Du z.B. mit einer Funktion wie dieser:

    function printLine(_Line){
      var line = _Line;
      var linebreak;
      var textnode;

    linebreak = document.createElement("br");
      textnode  = document.createTextNode(line);

    document.getElementById("ausgabe").appendChild(linebreak);
      document.getElementById("ausgabe").appendChild(textnode);
    }

    Löschen dann z.B. so:

    function clearOutput(){
      var arnold = document.getElementById("ausgabe");
      var adam   = arnold.cloneNode(false);

    arnold.parentNode.replaceChild(adam,arnold);
    }

    (99 Gummipunkte dem, der mir sagt warum ich ausgerechnet die Variablennamen "adam" und "arnold" gewählt habe ;-)

    so short

    Christoph Zurnieden

    1. 1.
      so wie ich das verstanden habe, gleicht die funktion die länge des Suchwortes mit der Länge der Stichwörter
      im Array ab. Aber wie funktionert das, dass bei 2 gleichlangen wörtern(auto, meer) das richtige gefunden
      wird. Haben die wörter bestimmte Werte die automatisch verglichen werden?

      2.

      die funktion findet nur genau die kompletten wörter im array, aber nicht wenn das suchwort ein teilwort
      eines stichwortes ist, wie ich das in meinem ansatz versucht habe.

      z.B.
      Eingabe: löscher

      Dann sollte eigentlich das Wort Feuerlöscher gefunden werden und nicht nur löscher.
      Wie kann man das erreichen. Vielleicht mit einem mehrdemensionalen Array.
      Ein Oberbegriff Auto(Automobil,Automobilmesse, Autowerkstatt...) und im unterarray sind jeweils die
      möglichen suchbegiffe definiert die eingegeben werden können oder beim begriff auto gefunden werden.

      Dann definiere ich eine Seite auf der Links zu allen Begriffen im Unterarray Auto sind und diese wird
      dann aufgerufen wenn eines der Wörter gefunden wurde.

      Wie sieht es mit Umlauten aus. Müssen die maskiert eingegeben werden(z.B. l&ouml;scher)?

      3.
      gibt es vielleicht ressourcen über das programmieren von suchfunktionen.
      Binäre Suche z.B. hat mir nichts gesagt. Was gibts da noch, wo kann man sich informieren.

      1. Hi,

        Ah, ich dachte schon, er kömmt nicht mehr wieder ;-)

        Haben die wörter bestimmte Werte die automatisch verglichen werden?

        Nein, das ist ein ganz normaler Vergleich. Die Buchstaben haben hier die unterschiedlichen Werte.

        die funktion findet nur genau die kompletten wörter im array, aber nicht wenn das suchwort ein teilwort
        eines stichwortes ist, wie ich das in meinem ansatz versucht habe.

        Ja, das ist ein Problem bei diesem Ansatz.
        Jetzt hast Du verschiedene Möglichkeiten. Entweder bist Du brutal und juckelst mit einer linearen Suche drüber, da kannst Du dann sogar reguäre Ausdrücke benutzen. Das kostet aber viel Rechenzeit, ist nur bei einer kurzen Liste zu empfehlen. Oder Du benutzt z.B. einen Suffix-Tree. Der kostet jedoch viel Speicher, da wird die Liste verdammt lang. Aber wenn Du eine Offlinesuche basteln willst und nur den Browser mit Javascript nehmen kannst mußt Du halt einige Kompromisse eingehen.

        Ich würde eine lineare Suche mit Regexen probieren:

        function linearSearch(needle, haystack){

        var len  = haystack.length -1;
          regex    = new RegExp(needle);

        while(len--){
            if (regex.test(haystack[len])){
              return len;
            }
          }
          return -1;
        }

        Der Code ist "ausse Lamäng" wie man hier sagt, also aus dem Ärmel geschüttelt und ungeprüft. Soll nur die Idee darstellen. (es fehlen auch noch Tests auf Fehler usw)

        Wenn Du sehr viel Material hast, das Du auf mehrere Dateien verteilen mußt wäre evt ein Bloomfilter nützlich. Aber das dürfte bei Deinen Anforderungen zuviel Aufwand im Voraus darstellen.

        Wie sieht es mit Umlauten aus. Müssen die maskiert eingegeben werden(z.B. l&ouml;scher)?

        Nein, müssen nicht.

        gibt es vielleicht ressourcen über das programmieren von suchfunktionen.

        Da darüber schon seit den Zeiten von Lord Byrons einz'ger Tochter selig geforscht wird, ist reichlich vorhanden. _Zu_ reichlich, wie Du schnell feststellen wirst.

        Binäre Suche z.B. hat mir nichts gesagt. Was gibts da noch, wo kann man sich informieren.

        Da Du damit anfängst kannst Du Dir höchstwahrscheinlich bei einigen Dingern nicht vorstellen, wie das funktionieren soll. Da hilft mitunter ein bewegtes Bild. Kannst Dich ja mal durch http://www.libraryreference.org/index.php?c=Computers/Algorithms/Animated durchklappern. Ansonsten ist dafür Wikipedia natürlich ein sehr guter Anlaufpunkt. Die sind da aber mehr theoretisch. Wenn Du aber z.B. aus mathematischen Kreisen kommst kannst Du damit wohl mehr anfangen als mit bewegten Bildchen.

        so short

        Christoph Zurnieden

        1. function linearSearch(needle, haystack){

          var len  = haystack.length -1;
            regex    = new RegExp(needle);

          while(len--){
              if (regex.test(haystack[len])){
                return len;
              }
            }
            return -1;
          }

          Der Code funktioniert generell.
          Nur mit der Funktion mit der ich den Rückgabewert von "return left"
          ausgebe, gibt nur den ersten wert aus.
          Was muss ich machen damit alle Suchergebnisse ausgegeben werden.

          Wenn ich die Daten direkt in der linearSearch funktion ausgebe werden alles Suchergebnisse ausgegeben, nur in meiner Funktion zum Schreiben der return werte klappt das nicht.

          1. Hi,

            Der Code funktioniert generell.

            Nein, tut er nicht, meine Schuld, sorry.

            Was muss ich machen damit alle Suchergebnisse ausgegeben werden.
            Wenn ich die Daten direkt in der linearSearch funktion ausgebe werden alles Suchergebnisse ausgegeben,

            Genau das. Nur halt nicht ausgeben, sondern in einer Liste sammeln wenn Du die weiterverarbeiten möchtest.

            function linearSearch(needle, haystack){
              var len   = haystack.length -1;
              var regex = new RegExp(needle);
              var ret   = new Array();
              var i     = 0;

            while(len--){
                if (regex.test(haystack[len])){
                   ret[i++] = haystack[len];
                 }
               }
              if(ret.length > 0){
                return ret;
              }
              return -1;
            }

            Nur mal so als Beispiel, da ich ja nicht weiß, wie Du das weiterverwenden möchtest.

            so short

            Christoph Zurnieden

            1. Hallo,

              hab nochmal ne Frage.

              Jetzt werden die Ergebnisse nebeneinander ausgeben sowie im array.
              ergebnis1,ergebnis2,...

              Ich möchte die aber untereinander haben. Hab schon einiges ausprobiert.
              Umwandeln in einen String(join()), mit replace() die Kommas in Zeilenumbrüche umwandeln.
              Aber es wird immer nur im String ausgebeben(ergebnis1<br>ergebnis2<br>...),(ergebnis1\nergebnis2\n...).

              hmm...

              Wat nu?

              mfg koerschgen2001

              1. Hi,

                Ich möchte die aber untereinander haben. Hab schon einiges ausprobiert.
                Umwandeln in einen String(join()), mit replace() die Kommas in Zeilenumbrüche umwandeln.
                Aber es wird immer nur im String ausgebeben(ergebnis1<br>ergebnis2<br>...),(ergebnis1\nergebnis2\n...).

                Da bräuchte ich denn doch mal die genaue Ausgaberoutine, denn mit document.write wie am Anfang würde es einwandfrei funktionieren.
                Hatte ich Dir nicht noch die showHit() Routine gegeben? Da schau einmal rein, wie das mit DOM gemacht wird. Sieht etwas kompliziert aus, ist es aber überhaupt nicht, ausnahmsweise völlig logisch aufgebaut.

                die Funktion showHit(var) fügt innerhalb das Elementes mit der ID "hitlist" erst einen erzwungenen Zeilensprung an das Ende des Inhaltes sowie direkt an den Anschluß den Textknoten(!) "var".

                function showHit(_Hit){
                  var temp1;
                  var temp2;
                  // Ich arbeite gerne mit einer lokalen Kopie, aber
                  // das ist Geschmacksache, funktioniert auch ohne.
                  var Hit = _Hit;

                // Man muß die einzelnen Knoten vor der Benutzung
                  // erstmal erzeugen.
                  // das Element "br"
                  temp1 = document.createElement("br");
                  // der Textknoten(!)
                  temp2 = document.createTextNode(Hit);
                  // element.appendChild(node) fügt den Knoten "node"
                  // an's Ende des Inhalts des Knotens mit der ID
                  // "hitlist"
                  document.getElementById("hitlist").appendChild(temp1);
                  document.getElementById("hitlist").appendChild(temp2);
                }

                Da showHit(var) "var" in einen Textknoten schreibt kannst Du da Elemente reinshreiben wie Du lustig bist, das wird als einfacher String -- als Textknoten ausgegeben. Wenn Du also z.B. zwischen jedem Mitglied Deines Ergebnisarrays ein Zeilensprung einfügen möchtest, dann mußt Du in einer kleinen Schleife für jedes Mitglied im Array die Funktion showHit() aufrufen.

                for(var i=0;i< ergebnissarray.length;i++){
                  showHit(ergebnissarray[i]);
                }

                Möchtest Du die Ergebnissliste anders formatieren (Du hattest "bold", gelle?), dann mußt Du den Code von showHit() ändern. Wenn Du die Einträge einzeln formatieren möchtest werden die Eintragsknoten zu Kindern des Formatknotens. Beispiel:

                function showHit(_Hit){
                  var temp1;
                  var temp2;
                  var Hit = _Hit;

                // bis hierhin noch gleich: Du erzeugst den
                  // Elementknoten "b" für "bold"
                  temp1 = document.createElement("b");
                  // und den Textknoten
                  temp2 = document.createTextNode(Hit);
                  // im Gegensatz zur ersten Version, muß hier der
                  // Textknoten "tmp2" _in_ den Elementknoten "tmp1"
                  tmp1.appendChild(tmp2);
                  // dann wieder das ganze Geraffel an's Ende des
                  // Ergebniscontainers.
                  document.getElementById("hitlist").appendChild(temp1);
                }

                Dann brauchst Du auch den kleinen Loop oben nicht, denn der würde so etwas wie "<b>eins</b><b>zwei</b> ... " erzeugen. Das erscheint mir doch ein wenig redundant ;-)

                Du könntest natürlich auch alles in ein "span" packen udn dann per CSS formatieren, das Du evt auch noch showHit() als zweites Argument beigibst. Ein Attribut wird eigentlich genauso erzeugt wie ein Element:

                var spanNode       = document.createElement("span");
                // Attribute "style" erzeugen
                var attStyle       = document.createAttribute("style");
                // Das Attribut mit Werten belegen
                attStyle.nodeValue = "background-color:green;" +
                                     "color:red;";
                // Das Attribut einem Element, hier: "spanNode" zufügen.
                spanNode.setAttributeNode(attStyle);

                so short

                Christoph Zurnieden