2012-04-21 8 views
8

que tiene una matriz con matrices anidadas que tiene este aspecto:Javascript indexOf para una matriz de matrices no encontrar variedad

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

Cuando intento y encontrar si la matriz tw contiene una aprobada en serie, siempre me un resultado de -1.

Por ejemplo:

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

tanto return -1, a pesar de que el primer objeto de la matriz es [3,0] ¿Cómo puedo saber si una matriz específica de las matrices está contenida en mi matriz?

Ah, y solo lo he probado en IE9 hasta el momento.

+2

[indexOf compara searchElement a elementos de la matriz usando igualdad estricta -el mismo método utilizado por el ===, o triples-iguales, operador] (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf) - No veo que una matriz sea el valor objetivo en [inarray] (http://api.jquery.com/jQuery.inArray/) – mplungjan

+0

Sugerí editar la etiqueta jQuery porque ' $ .inArray' junto con otros cambios menores, sin embargo, no estoy del todo seguro de si eso es jQuery o si quieres soluciones jQuery (deshacer/mejorar/rechazar si ese es el caso) – ajax333221

Respuesta

10

Eso es porque estás buscando un objeto diferente. indexOf() usa comparaciones de igualdad estrictas (como el operador ===) y [3, 0] === [3, 0] devuelve falso.

Tendrá que buscar manualmente. He aquí un ejemplo utilizando una función más genérica indexOf() que utiliza una función comparador personalizado (con una mejora sugerida por @ ajax333221 en los comentarios):

// 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

, mira esto [ejemplo actualizado ] (http://jsfiddle.net/Da5GS/2/) (el otro jsFiddle estaba equivocado) de por qué debería usar 'if (i en arr && comparer (arr [i], val))' – ajax333221

+0

@ ajax333221: Ahhhh, yo pensaste que estabas suggiendo esting usando 'for ... in'. Lo siento. Sí, eso es definitivamente una mejora, aunque no hace ninguna diferencia para el caso de esta pregunta en particular y yo diría que establecer explícitamente una propiedad de matriz en 'undefined' es pedir problemas. Actualizaré mi respuesta. –

+0

gracias por la aclaración. Esto funciona perfectamente! –

2

arrays son objetos . [3, 0] no es igual a [3, 0] ya que son objetos diferentes. Por eso tu inArray falla.

0

Esto es porque $.inArray y indexOf ambos usan una comparación superficial usando ===.

Dado que la matriz que está pasando es indexOf no exactamente la misma en la memoria que la de su matriz 2D, === devuelve falso. Tendrá que hacer una comparación profunda para encontrar la matriz de forma adecuada: desde un vistazo rápido a los documentos de jQuery, esto no está disponible allí.

2

Porque está comparando dos instancias de diferencia de matriz. La comparación de objetos devuelve true solo si son la misma instancia, no importa si contienen la misma información.

En su caso, usted podría utilizar este enfoque:

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

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

O algo más ORTODOX gustan:

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

Cuando la condición se puede ajustar depende del contenido de las matrices.

2

Para infinita búsqueda anidada:

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; 
} 

Notas:

  • soporta matrices anidadas infinitas
  • maneja correctamente matrices dispersas
  • utiliza cheques typeof

jsFiddle demo

+0

Paso horas pensando que 'NaN! == NaN' es' verdadero', y 'typeof null' es' "object" ' – ajax333221

0

Por qué no mantenerlo simple?

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; 
} 
Cuestiones relacionadas