Andmed ja otsing


Massiiv


Tavalises muutujas saame hoida ühte väärtust. Kui aga lehel on sarnaseid andmeid palju, siis igaüht omaette muutujas hoida on tülikas. Neid tuleb palju ning sobiva leidmine sealt ikkagi keerukas. Sarnaseid andmeid aitab koos hoida massiiv. Eesnimede loetelu saab näiteks teha nõnda:


            var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");

Selle peale luuakse loetelu, kus Juku poole saab pöörduda kujul eesnimed[0] ning Madise poole eesnimed[3]. Ehk siis lugemist alustatakse nullist ning viimase järjekorranumbriks on elementide arvust ühe jagu väiksem arv. Katsetamiseks juurde ka töötav koodinäide.



<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
            var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");
                function algus(){
                   document.getElementById("vastus").innerHTML=
                     "Loetelu alguses on "+eesnimed[0]+" ja "+eesnimed[1];
                }
         </script>
  </head>
  <body onload="algus()">
      <div id="vastus">
          
          </div>
  </body>
</html>

Näite tulemuseks:


Loetelu alguses on Juku ja Kati



Elementide arv


Javaskript annab õnneks mugavasti kätte massiivi elementide arvu - selleks omadus .length massiivimuutuja nime küljes. Sealtkaudu võimalik siis kohe arvutuse teel kätte saada massiivi viimane element. Eesnimede massiivis siis


eesnimed[eesnimed.length-1]


Näide tervikuna


<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
            var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");
                function algus(){
                   document.getElementById("vastus").innerHTML=
                     "Eesnimesid kokku on "+eesnimed.length+". Viimane neist "+
                            eesnimed[eesnimed.length-1]+".";
                }
         </script>
  </head>
  <body onload="algus()">
      <div id="vastus">
          
          </div>
  </body>
</html>

Ja tulemus


Eesnimesid kokku on 4. Viimane neist Madis.


Ülesandeid


* Koosta massiiv inimeste pikkustega. Trüki välja esimene ja viimane pikkus.

* Trüki välja teine ja eelviimane pikkus.



Järjekorranumbri järgi küsimine massiivist


Nagu kõiksugu muid väärtusi, nii ka massiivi elementide järjekorranumbreid saab küsida kasutaja käest. Siin siis võetakse eesnime number sisestuskastist ning kuvatakse vastav eesnimi.


<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
            var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");
                function otsi(){
                   var nimenr=parseInt(document.getElementById("kast1").value);
                   document.getElementById("vastus").innerHTML=
                     "Eesnimi nr. "+nimenr+" on "+eesnimed[nimenr];
                }
         </script>
  </head>
  <body>
      Mitmes eesnimi:
          <input type="text" id="kast1" />
          <input type="button" value="OK" onclick="otsi()" />
      <div id="vastus">
          
      </div>
  </body>
</html>






Juhusliku järjekorranumbriga element


Ka juhuarv toimib massiivi elemendi järjekorranumbri leidmise juures. Lihtsalt on kasulik hoolitseda, et järjekorranumbriks tuleks täisarv - parseInt pakub sellise võimaluse.


<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
            var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");
                function otsi(){
                   var juhuarv=Math.random(); //0 .. 0.99
                   var nimenr=parseInt(eesnimed.length*juhuarv);
                   document.getElementById("vastus").innerHTML=
                     "Eesnimi nr. "+nimenr+" on "+eesnimed[nimenr]+
                         ".<br /> Juhuarv oli "+juhuarv+".";
                }
         </script>
  </head>
  <body>
          <input type="button" value="Otsi juhuslik" onclick="otsi()" />
      <div id="vastus">
          
          </div>
  </body>
</html>






Ülesandeid

* Koosta massiiv ütlustega. Lehe avanemisel ilmub ekraanile neist

üks juhuslik ütlus.


* Erinevalt eelmisest teatatakse kasutajale, mitme ütluse vahel tal

on valida. Kasutaja sisestab soovitud ütluse järjekorranumbri ning

näeb vastaval kohal olevat ütlust.

* Koosta üks massiiv poiste eesnimedega ja teine tüdrukute eesnimedega.

Lehe avanemisel valitakse juhuslik poiss ja juhuslik tüdruk ning

teatatakse, et nemad lähevad esimestena tantsima.



Kordused


Massiivi andmete otsimiseks, muutmiseks ja töötlemiseks on kasulikuks abiliseks kordused. Kõigepealt väike näide korduse töötamise kohta


                 for(var i=0; i<3; i++){
                   document.getElementById("vastus").innerHTML+=i+" ";
                 }               

Tuumikuks siis for-tsükkel, kus iga sammuga liidetakse vastuse sisule (innerHTML) juurde tsükliloenduri i väärtus ning sinna lisatakse tühik, et arvud üksteisega kokku ei kasvaks. Tehtemärk += tähendab olemasolevale väärtusele millegi juurde lisamist, ilma, et peaks seda kohta korduvalt välja trükkima.




<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
                function algus(){
                 for(var i=0; i<3; i++){
                   document.getElementById("vastus").innerHTML+=i+" ";
                 }               
                }
         </script>
  </head>
  <body onload="algus()">
      <div id="vastus">
          
          </div>
  </body>
</html>

Väljund


0 1 2



Ülesandeid


* Tutvu tsükli näitega. Trüki arvude ruudud ühest kahekümneni
  (suurimaks siis 20*20 ehk 400).
* Luba kasutajal sisestada, mitmeni arvude ruute soovitakse


Tsükkel ja massiiv


Sarnaselt tsükli abil saab välja trükkida või muul moel ette võtta ka kõik samas massiivis olevad eesnimed. Lihtsalt väljatrüki või muul moel kasutuse koha peal pole enam tsükliringi loendur, vaid küsitakse massiivist vastava järjekorranumbriga element. Praegusel juhul siis eesnimed[i].


<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
                var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");
                function algus(){
                 for(var i=0; i<eesnimed.length; i++){
                   document.getElementById("vastus").innerHTML+=eesnimed[i]+" ";
                 }               
                }
         </script>
  </head>
  <body onload="algus()">
      <div id="vastus">
          
          </div>
  </body>
</html>

Väljundiks:


Juku Kati Katrin Madis



Eelmises näites olid eesnimede vahel tühikud. Nõnda tekstina saab aga ka kõiki HTMLi korraldusi anda ja nendega funktsiooni töö tulemust mõjutada. Kui eesnimede vahele kirjutada reavahetusmärgend <br /> , siis kasutaja näeb iga nime omaette real.



<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
                var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");
                function algus(){
                 for(var i=0; i<eesnimed.length; i++){
                   document.getElementById("vastus").innerHTML+=
                       eesnimed[i]+"<br />";
                 }               
                }
         </script>
  </head>
  <body onload="algus()">
      <div id="vastus">
          
          </div>
  </body>
</html>

Kasutaja näeb tulemust nõnda:


Juku
Kati
Katrin
Madis


Tegelikult on kokkupandud HTML-kood selline:


Juku<br />Kati<br />Katrin<br />Madis<br />

Veebilehitseja aga teab, et <br /> käskluse peale tuleb teksti edasi näitama hakata järgmiselt realt ning nõnda näemegi ilusti üksteise all olevaid eesnimesid.


Veidi põhjalikumaks loetelu looomiseks on HTMLis nummerdamata loetelu (unordered list), mille loomise käsuks märgend <ul> ning iga elemendi alguse teadustamiseks <li>. Lõpud siis vastavalt </li> ja </ul>. Nimede loetelu nummerdamata loetelus HTMLis näeb välja


<ul>

<li>Juku</li>
<li>Kati</li>
<li>Katrin</li>
<li>Madis</li>
</ul>


Programmikoodiga sellist loetelu tekitades tuleb üksikud lõigud kokku koguda. Siinses näiteks on selleks muutuja t (nagu tulemus).


Algul antakse t-le väärtus <ul>. Jutumärgid seetõttu ümber, et tegemist tekstiga.


                 var t="<ul>";

Iga tsükliringi juures lisatakse vastava järjekorranumbriga eesnimi, mille ees <li> ja taga </li>


                   t+="<li>"+eesnimed[i]+"</li>";

Ning lõpuks loetelu lõpp </ul>.


                 t+="</ul>";

Sellisena saabki tulemuse lehel kuvamiskõlblikuks.


<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
                var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");
                function algus(){
                 var t="<ul>";
                 for(var i=0; i<eesnimed.length; i++){
                   t+="<li>"+eesnimed[i]+"</li>";
                 }               
                 t+="</ul>";
                 document.getElementById("vastus").innerHTML=t;
                }
         </script>
  </head>
  <body onload="algus()">
      <div id="vastus">
          
      </div>
  </body>
</html>




Ülesandeid


* Tutvu massiivi andmete trükkimise näidetega, tee näited läbi.

* Kirjuta iga eesnime välja kaks korda

* Trüki eesnimed ekraanile tagurpidises järjekorras

* Asenda <ul> <ol>'ga ning vaata, kuidas mummud nimede ees asenduvad järjekorranumbritega



Teksti otsimise käsk


Javaskripti levinud tööks veebilehel on andmete seast sobivate välja otsimine - kui nimekiri on pikk, siis aitab programmikood sisestatud lõigu järgi sobivad välja valida. Selle jaoks leidub tekstifunktsioon nimega indexOf - mis teatab, kas ja kust otsitav tekst leiti. Tekstis on programmeerimiskeelte tarvis tähed nummerdatud, kusjuures Javaskripti puhul hakkab nummerdamine nullist. Ehk siis eesnimes "Mart" on täht "M" järjekorranumbriga 0 ja täht "a" järjekorranumbriga 1. Ning kui küsin et "Mart".indexOf("a"), siis saan vastuseks 1. Kui aga küsin mõnd olematut tähte, näiteks "Mart".indexOf("u"), siis saan vastuseks -1, sest tähte "u" Mardi nimes pole. Järgnevalt väike demo, kuidas seda käsklust veebilehel kasutada.


Ühte tekstikasti sisestab kasutaja uuritava lause, teise kasti otsitava teksti. Käsklus


                 var koht=lause.indexOf(otsitav);                

püüab muutujasse nimega koht indexOf-käskluse tulemuse, kus otsiti lausest otsitavat. Kui lõik leiti, nädatakse tähe järjekorranumbrit mitmendast lõik hakkab. Kui mitte, siis vastavaks koodiks olevat arvu -1.



<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
                function otsi(){
                 var lause=document.getElementById("kast1").value;
                 var otsitav=document.getElementById("kast2").value;
                 var koht=lause.indexOf(otsitav);                
                 document.getElementById("vastus").innerHTML=
                   "Otsitav kohal "+koht;
                }
         </script>
  </head>
  <body>
    Uuritav lause:
      <input type="text" id="kast1" value="Muna ja kana" />
        Otsitav tekst:
      <input type="text" id="kast2" value="ja" />
          <input type="button" value="Otsi" onclick="otsi()" />
      <div id="vastus">
          
      </div>
  </body>
</html>

Kui lauseks "Muna ja kana" ning tekstiks "ja", siis vastuseks 5, sest tähe "j" järjekorranumber on 5 ("M"-tähe number on 0).




Samas lauses aga kukk puudub ning vastuseks on miinus üks.




Saadud arve on võimalik kasutajale koos selgitustega näidata. Tingimuslause abil tasub kindlaks teha, et kui leitud koha väärtus on -1, siis võib kasutajale selgesõnaliselt teada anda, et lauses puudub otsitav lõik. Muul juhul aga öeldakse, kust otsitav leiti.


<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
                function otsi(){
                 var lause=document.getElementById("kast1").value;
                 var otsitav=document.getElementById("kast2").value;
                 var koht=lause.indexOf(otsitav);       
                 if(koht==-1){
                   document.getElementById("vastus").innerHTML= 
                     "Lauses puudub "+otsitav
                 } else {
                   document.getElementById("vastus").innerHTML=
                     "Otsitav kohal "+koht;
                 }
                }
         </script>
  </head>
  <body>
    Uuritav lause:
      <input type="text" id="kast1" value="Muna ja kana" />
        Otsitav tekst:
      <input type="text" id="kast2" value="ja" />
          <input type="button" value="Otsi" onclick="otsi()" />
      <div id="vastus">
          
      </div>
  </body>
</html>

Samade lausete puhul siis saab nüüd koos selgitustega vasted.





Otsing massiivist


Edasi piisab lõigu otsimise näide kokku panna varasema massiivi elementide näitamise näitega. Iga eesnime puhul kontrollitakse, et kas otsitav lõik selles eesnimes leidub. Kui jah, siis lisatakse vastav eesnimi näidatavate loetellu. Kui ei leidu, siis ei lisata ning seda ekraanil ei näe. Vastav lõik eraldi välja tooduna:


                   if(eesnimed[i].indexOf(otsitav)!=-1){
                     t+="<li>"+eesnimed[i]+"</li>";
                   }


Kui muidu koostati loetelu nõnda, et pandi kõik massiivis olevad eesnimed loetellu


                 var t="<ul>";
                 for(var i=0; i<eesnimed.length; i++){
                   t+="<li>"+eesnimed[i]+"</li>";
                 }               
                 t+="</ul>";

siis nüüd lisandus for-tsükli sisse if-tingimuslause, mille abil vaid tingimusele vastavad eesnimed näidatakse:



                 var t="<ul>";
                 for(var i=0; i<eesnimed.length; i++){
                   if(eesnimed[i].indexOf(otsitav)!=-1){
                     t+="<li>"+eesnimed[i]+"</li>";
                   }
                 }               
                 t+="</ul>";

Töötav näide tervikuna:



<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
                var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");
                function otsi(){
                 var otsitav=document.getElementById("kast2").value;
                 var t="<ul>";
                 for(var i=0; i<eesnimed.length; i++){
                   if(eesnimed[i].indexOf(otsitav)!=-1){
                     t+="<li>"+eesnimed[i]+"</li>";
                   }
                 }               
                 t+="</ul>";
                 document.getElementById("vastus").innerHTML=t;
                }
         </script>
  </head>
  <body>

        Otsitav tekst:
      <input type="text" id="kast2" />
          <input type="button" value="Otsi" onclick="otsi()" />
      <div id="vastus"></div>
  </body>
</html>




Suur- ja väiketähed


Javaskript eristab suur- ja väiketähti. Ehk siis K ning k on tema jaoks sama erinevad tähed kui a ja b. Kasutaja aga otsimise ajal ei pruugi jälgida ega eristada, kumma suurusega tähe järgi ta parajasti otsida soovib. Kasutajat häirivate üllatuste vältimiseks saab otsingulehe panna käituma nõnda, et sobivad eesnimed leitakse nii suurte kui väikseste tähtede järgi otsides. Üheks mooduseks on nii kasutaja sisestatud tekst kui ka võrreldav nimi muuta võrdlemise ajaks väiketähtedeks. Sellisel juhul pole vahet, milline oli tähekõrgus enne - võrreldakse ikkagi lõpuks ühesuguseid sümboleid. Kasutaja sisestatav tekst tehakse väikseks kohe andmete sisselugemisel.


                 var otsitav=
                    document.getElementById("kast2").value.toLowerCase();


Massiivist eesnimesid võttes aga tehakse nad väikseks ükshaaval iga võrdlemise tarbeks.


                   if(eesnimed[i].toLowerCase().indexOf(otsitav)!=-1){
                     t+="<li>"+eesnimed[i]+"</li>";
                   }

Õigemini massiivis olev nimi ise jääb endiselt nõnda nagu ta on, aga võrdlemiseks tehakse koopia mille toLowerCase() väljastab.


Otsingurakendus tekstina:


<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
                var eesnimed=new Array("Juku", "Kati", "Katrin", "Madis");
                function otsi(){
                 var otsitav=
                    document.getElementById("kast2").value.toLowerCase();
                 var t="<ul>";
                 for(var i=0; i<eesnimed.length; i++){
                   if(eesnimed[i].toLowerCase().indexOf(otsitav)!=-1){
                     t+="<li>"+eesnimed[i]+"</li>";
                   }
                 }               
                 t+="</ul>";
                 document.getElementById("vastus").innerHTML=t;
                }
         </script>
  </head>
  <body onload="otsi()">
        Otsitav tekst:
      <input type="text" id="kast2" onkeyup="otsi()" />
      <div id="vastus"></div>
  </body>
</html>




Ülesandeid


* Tutvu kasutaja otsitavate nimede näitamisega

* Näita vaid neid nimesid, mis algavad otsitava tekstiga

(indexOf(otsitav)==0)
* Näita kõik leitud nimed välja väiketähtedena



Otsing kirjetest

Päriselus ette tulevate andmete juures kipub sageli olema rohkem kui üks tunnus. Raamatul on pealkiri ja autor ja ilmumisaeg. Pildil mõõtmed, tegemisaeg, koht ja vahel kirjeldus. Ning mõnikord neid tunnuseid ehk välju võib andmetel päris palju olla. Kui otsitakse korvpallureid, siis pigem kahesaja ringis olev vastav väärtus pikkuse juures võib sobiva vihje anda. Kui aga kehakaal samale arvule läheneb, siis pole vastaval tegelasel ehk suuremate võistluste juures kuigi palju peale hakata. Õnneks võimaldab ka Javaskript tunnuseid nõnda eraldi jagada ja pärast vaadata, et millist neist just parajasti kätte saada tahetakse. Järgnevalt näide, kus laste andmeteks on nende eesnimed ja sünniajad. Otsitakse eesnime järgi, aga näidatakse mõlemat tunnust. Eelnevalt väike seletus andmestiku kirjapaneku kohta.


Luuakse uus massiiv nimega lapsed. Tühi massiiv näeks välja


var lapsed=[];


Siia aga on võimalik kohe väärtused ka sisse panna. Ühe lapse andmed kannatab kirja panna kujul

                   {"eesnimi":"Juku", "synniaeg": "13.06"}

Igal lapsel siis kaks tunnust: eesnimi ja synniaeg. Teispool koolonit nende väärtused konkreetse lapse puhul. Kui laste andmeid mitu järjest ja komadega eraldatult on, siis tulebki tulemuseks laste massiiv.



                var lapsed=[
                   {"eesnimi":"Juku", "synniaeg": "13.06"},
                   {"eesnimi":"Kati", "synniaeg": "11.06"},
                   {"eesnimi":"Mati", "synniaeg": "25.08"},
                   {"eesnimi":"Madis","synniaeg": "09.02"}
                ];


Sellist andmete kirjapanekut nimetatakse JSON-iks (JavaScript Object Notation). Sellisel kujul programmile etteantud andmeid saab mugavasti koodis kasutada. Muutuja lapsed on täiesti tavaline massiiv, lapsed[0] näiteks massiivi esimene laps. Kui aga soovitakse tema eesnime, siis tuleb küsida lapsed[0].eesnimi. Soovides tsükli ehk korduslause abil järgemööda kõikide laste poole pöörduda, tuleb kantsulgudes oleva arvu asemele panna tsüklimuutuja. Nõnda siis kontrollitakse i-nda lapse puhul, et kas tema väiketähtedena vaadatud eesnimes on otsitav tekst.


                   if(lapsed[i].eesnimi.toLowerCase().indexOf(otsitav)!=-1){}


Loetellu näitamiseks aga lisatakse eesnimi koos sünniajaga.


                     t+="<li>"+lapsed[i].eesnimi+ " "+
                           lapsed[i].synniaeg+"</li>";

Edasi juba otsingu kood tervikuna.


<!doctype html>
<html>
  <head>
     <title>Otsing</title>
         <meta charset="utf-8" />
         <script>
                var lapsed=[
                   {"eesnimi":"Juku", "synniaeg": "13.06"},
                   {"eesnimi":"Kati", "synniaeg": "11.06"},
                   {"eesnimi":"Mati", "synniaeg": "25.08"},
                   {"eesnimi":"Madis","synniaeg": "09.02"}
                ];
                function otsi(){
                 var otsitav=
                    document.getElementById("kast2").value.toLowerCase();
                 var t="<ul>";
                 for(var i=0; i<lapsed.length; i++){
                   if(lapsed[i].eesnimi.toLowerCase().indexOf(otsitav)!=-1){
                     t+="<li>"+lapsed[i].eesnimi+ " "+
                           lapsed[i].synniaeg+"</li>";
                   }
                 }               
                 t+="</ul>";
                 document.getElementById("vastus").innerHTML=t;
                }
         </script>
  </head>
  <body onload="otsi()">
        Otsitav tekst:
      <input type="text" id="kast2" onkeyup="otsi()" />
      <div id="vastus"></div>
  </body>
</html>




Ülesandeid


* Tutvu eesnimede ja sünnipäevade vaatamise näitega.

* Kuva sünnipäev eespool, eesnimi tagapool


* Koostage väike sõnaraamat, kus näidatakse sisestatud sõna vasteid.


Sõnaraamat.


Sõnu koos vastetega vähemasti ühe õpiku õppetüki jagu.

Kasutaja sisestatud tähtede peale näidatakse välja sobivad

sõnad ja vasted, leht on mõnevõrra kujundatud

(näiteks vasted üle ühe erinevat värvi)

Viisakas on näiteks kasutada mõnd olemasolevat mobiililehe malli (template)


Pikkuste joonis.


Massiivis on inimeste nimed ja pikkused.

Joonisele kuvatakse vaid nende inimeste nimed, kes on etteantud pikkuste

vahemikus. Nime kõrval näidatakse pikkus vastava kõrgusega tulbana.



Asukohad parklas.


Massiivis on kirjas autode numbrid ning nende

x- ja y-koordinaadid parklas. Sisestades autonumbri või selle osa

näeb otsingule vastavaid autosid parklas (koos õige asukohaga).