IneX: Crash beim Durchlaufen eines Arrays

Ich habe eine Funktion geschrieben, die das Ziel hat ein bestehendes Array nach einem übergebenen Wert zu druchsuchen. Es sind alles Integer, also Zahlen.

Das Problem ist aber, dass das Script eine Endlosschleife generiert, sofern ich eine } else { .... Anweisung für die Ausgabe des Resultats anwende. Hier der Code:

function search_array(from_array,search_int)
{
 var arr = from_array;
 var obj = search_int;
 if (obj != ""){
  for (i = 0; i < arr.length; i++){
   if (arr[i] != obj){
    return 1;
   } else {
    return -1;
   }
  }
 }
}

Sobald das Script auf einen passenden Wert trifft, stürzt es ab. (Zur Info: wenn ein Wert im Array enthalten ist, ist es schlecht. Deshalb die Prüfung ob ein Wert NICHT im Array existiert. Stichwort "Blacklist")

Ich habe schon einige Varianten versucht, z.B. anstatt ein return eine globale Variable mit 1 oder -1 zu beschreiben und auf diese zuzugreiffen; mit dem gleichen Resultat.

Hat jemand eine Idee, woran das liegt bzw. wo ich einen Fehler mache?

  1. Hallo IneX,

    ich glaube, die Schleife wird nur einmal durchlaufen und je nach Wert im Array an Stelle 0 wird die Funktion mit Rückgabe 1 oder -1 beendet. Es wird also nur das erste Element überprüft. Lass den "else-Zweig" in der Schleife einfach weg und setze hinter die Schleife ein "return -1". Wird das Element gefunden, werden die Schleife und die Funktion mit return 1 beendet, wird das Element nicht gefunden, läuft die Schleife bis zum Schluss und die Funktion wird dann mit return -1 beendet.

    Gruß, Jürgen

    1. Lass den "else-Zweig" in der Schleife einfach weg und setze hinter die Schleife ein "return -1". Wird das Element gefunden, werden die Schleife und die Funktion mit return 1 beendet, wird das Element nicht gefunden, läuft die Schleife bis zum Schluss und die Funktion wird dann mit return -1 beendet.

      Hi Jürgen

      Danke für deine Hilfe. Wenn ich Else weglasse funktioniert es trotzdem nicht. IE meldet jeweils, dass das Script eine "Verzögerung im Internet Explorer" hervorruft und ob ich das Script weiterhin ausführen möchte oder nicht (wobei auch gleich die Frage von Struppi beantwortet wäre.

      1. Hallo IneX,

        dann zeig mal deine aktuelle Version.

        Gruß, Jürgen

        1. dann zeig mal deine aktuelle Version.

          function search_array(from_arr,search_int)
          { /* FÜHRT ZU EINER UEBERLASTUNG DES SCRIPTS */
           var arr = from_arr;
           if (search_int){
            for (var i = 0; i < arr.length; i++){
             if (arr[i] == search_int){
              return 1;
             }
             return -1;
            }
           }
          }

          1. Hallo IneX,

            function search_array(from_arr,search_int)
            { /* FÜHRT ZU EINER UEBERLASTUNG DES SCRIPTS */
            var arr = from_arr;

            warum das Umspeichern?

            if (search_int){
              for (var i = 0; i < arr.length; i++){
               if (arr[i] == search_int){
                return 1;
               }
               return -1;
              }
            }
            }

            • Wenn search_int nicht übergeben wird, wird nichts "returnt".
            • Die Schleife wird immer noch nur einmal durchlaufen. Das return -1 gehört ans Ende der Funktion.
            • Ich sehe nicht, wie diese Funktion den Browser "ins Jenseits" schicken kann. Repariere das mit dem "return" und zeig dann auch mal, wer die Funktion wie und wo und mit welchen Parametern aufruft.

            Gruß, Jürgen

          2. function search_array(from_arr,search_int)
            { /* FÜHRT ZU EINER UEBERLASTUNG DES SCRIPTS */

            Aber nicht wegen dieser Funktion.

            if (search_int){
              for (var i = 0; i < arr.length; i++){
               if (arr[i] == search_int){
                return 1;
               }
               return -1;
              }

            Die Schleife läuft, wie dir Jürgend auch schon gesagt hat, immer noch nur einmal durch.

            Also ich würde das ganze soweiso mit einem Prototypen machen, dann kannst du das auf alle deine Arrays anwenden.

            Array.prototype.isIn = function(val) {  
             if(val) {  
              for(var i = 0; i < this.length; i++) {  
               if(this[i] == val) return i;  
              }  
             }  
             return -1;  
            };  
              
            var test = [1,2,3,4,5];  
            alert( test.isIn(4) )  
            alert( test.isIn(0) )
            

            Struppi.

  2. function search_array(from_array,search_int)
    {
    var arr = from_array;
    var obj = search_int;

    Die Variabel obj dürfte nicht nötig sein.

    if (obj != ""){

    hier kannst du schreiben
    if (!obj){

    for (i = 0; i < arr.length; i++){

    Das ist schlecht!
    Globale Schleifenvairabeln solltest du immer vermeiden
    for (var i = 0; i < arr.length; i++){

    if (arr[i] != obj){
        return 1;
       } else {
        return -1;
       }

    D.h. du willst die Schleife nur einmal durchlaufen lassen?

    Sobald das Script auf einen passenden Wert trifft, stürzt es ab.

    Was heiß abstürzen? Bluescreen?
    bekommst du keine Fehlermeldung?

    Struppi.

    1. Hi,

      if (obj != ""){

      hier kannst du schreiben
      if (!obj){

      Kleine Korrektur:
      if(obj){

      mfG,
      steckl

  3. gruss IneX,

    Ich habe eine Funktion geschrieben, die das Ziel hat,
    ein bestehendes Array nach einem übergebenen Wert zu
    druchsuchen. Es sind alles Integer, also Zahlen.

    Das Problem ist aber, dass das Script eine Endlosschleife
    generiert ...
    ...
    Sobald das Script auf einen passenden Wert trifft,
    stürzt es ab. (Zur Info: wenn ein Wert im Array
    enthalten ist, ist es schlecht. Deshalb die Prüfung
    ob ein Wert NICHT im Array existiert. Stichwort "Blacklist")

    ... Hier der Code:

    function search_array(from_array,search_int)

    {
    var arr = from_array;
    var obj = search_int;

    ~~~javascript
      /*  
        [from_array] und [search_int] liegen bereits im  
        *wirkungsbereich* Deiner funktion und muessen  
        daher nicht nochmal referenziert werden.  
      */
    

    if (obj != ""){
    [code lang=javascript]  /*
        auf [""], [0] und [false] immer strikt (!== bzw. ===)
        pruefen, denn es gilt:
        (("" == 0) === ("" == false) === (0 == false)) === true
      */

    
    >  ~~~javascript
    
    for (i = 0; i < arr.length; i++){  
    
    >    if (arr[i] != obj){ // siehe oben und [*1]  
    >     return 1;  
    >    } else {  
    >     return -1;  
    >    }  
    >   }  
    >  }  
    > }
    
    

    [*1] Dein code erzwingt ueber "return" bei (i === 0)
    den sofortigen ausstieg aus der schleife ...

    ... persoenlich halte ich das fuer schlechten stil und
    plaediere hiermit fuer den einsatz des stiefmuetterlich
    behandelten "break".

    unter beruecksichtigung moeglicher zukuenftiger array-
    methoden koenntest Du Deine methode auch [indexOf] nennen.
    und damit diese nicht allein im globalen namensraum
    abhaengen muss, darfst Du diese ruhig sowohl *statisch*
    als auch *prototypisch* an den [[Array]]-konstruktor tackern.

    siehe dazu auch:

    [http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf]

    hier ein moeglicher statischer entwurf ...

    // [[link:http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozGenerics.dev.js]]  
    //if (typeof Array.indexOf != "function") {  
      
      Array.indexOf = (function (obj, objLookingFor, idx) {  
      
      //var k, i = -1, l = ((typeof obj.length == "number") ? (obj.length) : (0));  
        var k, i = -1, l = (((obj instanceof Array) || ((typeof obj.length == "number") && ((typeof obj.item == "function") || (typeof obj.item == "object") || (typeof obj.item == "string") || (obj instanceof window.NodeList) || (obj instanceof window.HTMLCollection)))) ? (obj.length) : (0));  
      
      //[[link:http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf#Parameters]]  
        idx = ((idx && isNaN(Number(idx))) ? (parseInt(Number(idx), 10)) : (0));  
        idx = ((idx < 0) ? (Math.max(0,(l + idx))) : (idx));  
      
        for (k=idx; k<l; ++k) {  
        //if (obj[k] === objLookingFor) {  
          if ((obj[k] || obj.item(k)) === objLookingFor) {  
            i = k;  
            break;  
          }  
        }  
        return i;  
      });  
    //}
    

    ... und hier das prototypische gegenstück ...

    // [[link:http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozExtensions.dev.js]]  
    if (typeof Array.prototype.indexOf != "function") {  
      
      Array.prototype.indexOf = (function (obj, idx) {  
      
      //[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf#Parameters]  
        idx = ((idx && isNaN(Number(idx))) ? (parseInt(Number(idx), 10)) : (0));  
        idx = ((idx < 0) ? (Math.max(0,(this.length + idx))) : (idx));  
        var k, i = -1;  
        for (k=idx; k<this.length; ++k) {  
          if (this[k] === obj) {  
            i = k;  
            break;  
          }  
        }  
        return i;  
      });  
    }
    

    ... darauf liessen sich dann auch noch die passenden eigenen [contains]-methoden pfropfen:

    // [http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozGenerics.dev.js]  
    //if (typeof Array.contains != "function") {  
      
      Array.contains = (function (obj, objLookingFor) {  
      
        return (Array.indexOf(obj, objLookingFor) >= 0);  
      });  
    //}
    
    // [http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozExtensions.dev.js]  
    if (typeof Array.prototype.contains != "function") {  
      
      Array.prototype.contains = (function (obj) {  
      
        return (this.indexOf(obj) >= 0);  
      });  
    }
    

    so long - peterS. - pseliger@gmx.net

    --
    »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
    Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
    ie:( fl:) br:> va:( ls:& fo:) rl:| n3;} n4:} ss:} de:µ js:} mo:? zu:]
    1. Hi Peter

      Danke für deinen Input zu meinem Problem. Leider übersteigen deine Beispiele meine JavaScript Kenntnisse, weshalb ich die Funktionen nicht an mein Script adaptieren soll; aber vorweg: es kann doch nicht sein, dass es so kompliziert ist, herauszufinden ob ein Wert in einem Array vorkommt oder nicht?? Das sollte doch mit einem simplen durchlaufen des Arrays, im Ansatz wie in meinem Post zu diesem Problem, zu lösen sein??

      Gruss
      IneX

      [*1] Dein code erzwingt ueber "return" bei (i === 0)
      den sofortigen ausstieg aus der schleife ...

      ... persoenlich halte ich das fuer schlechten stil und
      plaediere hiermit fuer den einsatz des stiefmuetterlich
      behandelten "break".

      unter beruecksichtigung moeglicher zukuenftiger array-
      methoden koenntest Du Deine methode auch [indexOf] nennen.
      und damit diese nicht allein im globalen namensraum
      abhaengen muss, darfst Du diese ruhig sowohl *statisch*
      als auch *prototypisch* an den [[Array]]-konstruktor tackern.

      siehe dazu auch:

      [http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf]

      hier ein moeglicher statischer entwurf ...

      // [[link:http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozGenerics.dev.js]]

      //if (typeof Array.indexOf != "function") {

      Array.indexOf = (function (obj, objLookingFor, idx) {

      //var k, i = -1, l = ((typeof obj.length == "number") ? (obj.length) : (0));
          var k, i = -1, l = (((obj instanceof Array) || ((typeof obj.length == "number") && ((typeof obj.item == "function") || (typeof obj.item == "object") || (typeof obj.item == "string") || (obj instanceof window.NodeList) || (obj instanceof window.HTMLCollection)))) ? (obj.length) : (0));

      //[[link:http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf#Parameters]]
          idx = ((idx && isNaN(Number(idx))) ? (parseInt(Number(idx), 10)) : (0));
          idx = ((idx < 0) ? (Math.max(0,(l + idx))) : (idx));

      for (k=idx; k<l; ++k) {
          //if (obj[k] === objLookingFor) {
            if ((obj[k] || obj.item(k)) === objLookingFor) {
              i = k;
              break;
            }
          }
          return i;
        });
      //}

      
      >   
      >   
      > ... und hier das prototypische gegenstück ...  
      >   
      >   
      > ~~~javascript
      
      // [[link:http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozExtensions.dev.js]]  
      
      > if (typeof Array.prototype.indexOf != "function") {  
      >   
      >   Array.prototype.indexOf = (function (obj, idx) {  
      >   
      >   //[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf#Parameters]  
      >     idx = ((idx && isNaN(Number(idx))) ? (parseInt(Number(idx), 10)) : (0));  
      >     idx = ((idx < 0) ? (Math.max(0,(this.length + idx))) : (idx));  
      >     var k, i = -1;  
      >     for (k=idx; k<this.length; ++k) {  
      >       if (this[k] === obj) {  
      >         i = k;  
      >         break;  
      >       }  
      >     }  
      >     return i;  
      >   });  
      > }
      
      

      ... darauf liessen sich dann auch noch die passenden eigenen [contains]-methoden pfropfen:

      // [http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozGenerics.dev.js]

      //if (typeof Array.contains != "function") {

      Array.contains = (function (obj, objLookingFor) {

      return (Array.indexOf(obj, objLookingFor) >= 0);
        });
      //}

      
      >   
      >   
      > ~~~javascript
      
      // [http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozExtensions.dev.js]  
      
      > if (typeof Array.prototype.contains != "function") {  
      >   
      >   Array.prototype.contains = (function (obj) {  
      >   
      >     return (this.indexOf(obj) >= 0);  
      >   });  
      > }
      
      

      so long - peterS. - pseliger@gmx.net

      1. ...weshalb ich die Funktionen nicht an mein Script adaptieren soll;

        nicht "soll", sondern "kann" ;-)

      2. .. es kann doch nicht sein, dass es so kompliziert ist, herauszufinden ob ein Wert in einem Array vorkommt oder nicht?? Das sollte doch mit einem simplen durchlaufen des Arrays, im Ansatz wie in meinem Post zu diesem Problem, zu lösen sein??

        Ist es auch und ich hab dir auch bereits ein paar Sachen gezeigt wo bei deinem Code die Probleme sind.

        Struppi.

      3. hallo again IneX

        ... aber vorweg: es kann doch nicht sein, dass es so kompliziert ist,
        herauszufinden ob ein Wert in einem Array vorkommt oder nicht??

        ist es auch nicht, und Du hast sowohl von Jürgen als auch von Struppi
        und mir jeweils als antwort erhalten, dass Deine schleife niemals das
        komplette array durchlaeuft, da Du diese schon nach dem ersten vergleich
        ueber "return" verlaesst.

        ... haendchen halten ist zwar nicht so mein ding, aber wegen ...

        Hi Peter

        Danke für deinen Input zu meinem Problem. Leider übersteigen deine
        Beispiele meine JavaScript Kenntnisse, ...

        ... hol' ich Dich mal direkt bei Deinem problem ab:

        Du moechtest jeweils das komplette array iterieren, denn erst nach dem
        letzten negativ ausfallenden vergleich - letzter array-eintrags versus
        vorgegebener vergleichswert - kannst Du Dir sicher sein, dass ebendiese
        vorgabe nicht im array vorkommt. dafuer darfst Du die iteration sofort
        abbrechen, sobald ein vergleich positiv ausfaellt.

        //function search_array(from_array,search_int) {  
          function arrayContains(arr, obj) { //  Du suchst ein objekt in einem array.  
          
            var i, len = arr.length, isInArray = false; // default rueckgabewert [1].  
          
            for (i=0; i<len; ++i) { // durchlaeuft die schleife ...[2]...  
          
              if (arr[i] === obj) { // [1] strikte pruefung auf *vorhandensein*.  
          
                isInArray = true; // [1] boolscher default-rueckgabewert wird geaendert.  
                break; // [2].., und bricht den kompletten zyklus beim ersten treffer ab.  
              }  
            }  
            return isInArray; // [1] [false], wenn kein einziger vergleich etwas hergab.  
          }
        

        wie unschwer zu erkennen ist, gibt es im kern dieser funktionalitaet -
        "wie wird geprueft, wann und auf welche art wird die pruefende iteration
        abgebrochen" - eine grosse naehe zu den anderen von mir vorgeschlagenen
        universelleren loesungen.

        guten stil bewiese man jetzt noch, wenn man das argument [arr] einer
        typpruefung unterzoege.

        so long - peterS. - pseliger@gmx.net

        --
        »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
        Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
        ie:( fl:) br:> va:( ls:& fo:) rl:| n3;} n4:} ss:} de:µ js:} mo:? zu:]