2012-04-21 14 views
8

Ho un array con matrici nidificate che assomiglia a questo:Javascript indexOf per un array di array non trovare gamma

var tw = [[3, 0], [11, 0], [3, 14], [11, 14]]; 

Quando provo e trovare se la matrice tw contiene un passato in ordine, ho sempre arrivare un risultato di -1.

Ad esempio:

var test = $.inArray([3, 0], tw); 
var test2 = tw.indexOf([3, 0]); 

entrambi di ritorno -1, anche se il primo oggetto nella matrice è [3,0] Come faccio a sapere se una gamma specifica di array è contenuta nel mio array?

Oh, e finora l'ho provato solo su IE9.

+2

[indexOf confronta searchElement agli elementi della matrice mediante uguaglianza rigorosa -il stesso metodo usato dal ===, o triple-eguali, operatore] (https://developer.mozilla.org/en/JavaScript/Riferimento/Global_Objects/Array/indexOf) - Non vedo un array come valore di destinazione in [inarray] (http://api.jquery.com/jQuery.inArray/) o – mplungjan

+0

Ho suggerito-modificare il tag jQuery perché ' $ .inArray' insieme ad altre modifiche minori, tuttavia non sono del tutto sicuro che si tratti di jQuery o se si desidera soluzioni jQuery (annulla/migliora/rifiuta se questo è il caso) – ajax333221

risposta

10

Questo perché stai cercando un oggetto diverso. indexOf() utilizza confronti di uguaglianza rigorosa (come l'operatore ===) e [3, 0] === [3, 0] restituisce false.

Avrete bisogno di cercare manualmente. Ecco un esempio con un più generico indexOf() funzione che utilizza una funzione di confronto personalizzato (con un miglioramento suggerito da @ ajax333221 nei commenti):

// Shallow array comparer 
function arraysIdentical(arr1, arr2) { 
    var i = arr1.length; 
    if (i !== arr2.length) { 
     return false; 
    } 
    while (i--) { 
     if (arr1[i] !== arr2[i]) { 
      return false; 
     } 
    } 
    return true; 
} 

function indexOf(arr, val, comparer) { 
    for (var i = 0, len = arr.length; i < len; ++i) { 
     if (i in arr && comparer(arr[i], val)) { 
      return i; 
     } 
    } 
    return -1; 
} 

var tw = [[3, 0], [11, 0], [3, 14], [11, 14]]; 
alert(indexOf(tw, [3, 0], arraysIdentical)); // Alerts 0 
+0

, vedere questo [esempio aggiornato ] (http://jsfiddle.net/Da5GS/2/) (l'altro jsFiddle era sbagliato) del perché dovresti usare 'if (i in arr && comparer (arr [i], val))' – ajax333221

+0

@ ajax333221: Ahhhh, I pensavo fossi un sugg esting usando 'for ... in'. Scusate. Sì, questo è sicuramente un miglioramento, anche se non fa alcuna differenza nel caso di questa particolare domanda e direi che l'impostazione esplicita di una proprietà di matrice su 'indefinito' sta chiedendo dei problemi. Aggiornerò la mia risposta –

+0

grazie per il chiarimento. Funziona perfettamente! –

2

Gli array sono oggetti. [3, 0] non è uguale a [3, 0] poiché sono oggetti diversi. Ecco perché il tuo inArray fallisce.

0

Questo perché $.inArray e indexOf utilizzano entrambi un confronto superficiale utilizzando ===.

Poiché la matrice che si sta passando è a indexOf non la stessa identica memoria di quella nel proprio array 2D, === restituisce false. Avrai bisogno di fare un confronto approfondito per trovare l'array correttamente - da una rapida occhiata ai documenti jQuery, questo non è disponibile lì.

2

Poiché si stanno confrontando due istanze di differenza di matrice. Confrontando gli oggetti restituisce true solo se sono la stessa istanza, non importa se contengono gli stessi dati.

Nel tuo caso, è possibile utilizzare questo approccio:

var tw = [[3, 0], [11, 0], [3, 14], [11, 14]]; 

if (~tw.join(";").split(";").indexOf(String([3, 0]))) { 
    // ... 
} 

O qualcosa di più ortodossa piace:

if (tw.filter(function(v) { return String(v) === String([3, 10]) })[0]) { 
    // ... 
} 

Dove la condizione può essere regolata dipende dal contenuto degli array.

2

Per infinita ricerca nidificato:

function indexOfArr(arr1, fnd1) { 
    var i, len1; 

    //compare every element on the array 
    for (i = 0, len1 = arr1.length; i < len1; i++) { 

     //index missing, leave to prevent false-positives with 'undefined' 
     if (!(i in arr1)) { 
      continue; 
     } 

     //if they are exactly equal, return the index 
     if (elementComparer(arr1[i], fnd1)) { 
      return i; 
     } 
    } 

    //no match found, return false 
    return -1; 
} 

function elementComparer(fnd1, fnd2) { 
    var i, len1, len2, type1, type2, iin1, iin2; 

    //store the types of fnd1 and fnd2 
    type1 = typeof fnd1; 
    type2 = typeof fnd2; 

    //unwanted results with '(NaN!==NaN)===true' so we exclude them 
    if (!((type1 == "number" && type2 == "number") && (fnd1 + "" == "NaN" && fnd2 + "" == "NaN"))) { 

     //unwanted results with '(typeof null==="object")===true' so we exclude them 
     if (type1 == "object" && fnd1 + "" != "null") { 
      len1 = fnd1.length; 

      //unwanted results with '(typeof null==="object")===true' so we exclude them 
      if (type2 == "object" && fnd2 + "" != "null") { 
       len2 = fnd2.length; 

       //if they aren't the same length, return false 
       if (len1 !== len2) { 
        return false; 
       } 

       //compare every element on the array 
       for (i = 0; i < len1; i++) { 

        iin1 = i in fnd1; 
        iin2 = i in fnd2; 

        //if either index is missing... 
        if (!(iin1 && iin2)) { 

         //they both are missing, leave to prevent false-positives with 'undefined' 
         if (iin1 == iin2) { 
          continue; 
         } 

         //NOT the same, return false 
         return false; 
        } 

        //if they are NOT the same, return false 
        if (!elementComparer(fnd1[i], fnd2[i])) { 
         return false; 
        } 
       } 
      } else { 
       //NOT the same, return false 
       return false; 
      } 
     } else { 

      //if they are NOT the same, return false 
      if (fnd1 !== fnd2) { 
       return false; 
      } 
     } 
    } 

    //if it successfully avoided all 'return false', then they are equal 
    return true; 
} 

Note:

  • supporta array nidificati infinite
  • gestisce array sparsi correttamente
  • utilizza typeof controlli

jsFiddle demo

+0

Passo ore a capire che 'NaN! == NaN' è' true', e 'typeof null' è' "object" ' – ajax333221

0

Perché non mantenere le cose semplici?

function indexOfCustom (parentArray, searchElement) { 
    for (var i = 0; i < parentArray.length; i++) { 
     if (parentArray[i][0] == searchElement[0] && parentArray[i][1] == searchElement[1]) { 
      return i; 
     } 
    } 
    return -1; 
} 
Problemi correlati