2012-04-21 9 views
8

Mam tablicę z zagnieżdżonych tablic, które wygląda tak:JavaScript indexOf na tablicy tablic nie znajdując tablicy

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

Kiedy spróbować znaleźć jeśli tablica tw zawiera uchwalona w tablicy, zawsze dotrzesz wynik -1.

Na przykład:

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

zwracają -1, mimo że pierwszy obiekt w tablicy jest [3,0] Jak mogę dowiedzieć się, czy dany szereg tablic jest zawarte w moim tablicy?

Och, a do tej pory testowałem go tylko na IE9.

+2

[indexOf porównuje searchElement do elementów tablicy za pomocą ścisłego równości -tak samo metody wykorzystywane przez === lub potrójnych równymi operatora] (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf) - Nie widzę tablicy wartości docelowej w [inarray] (http://api.jquery.com/jQuery.inArray/) albo – mplungjan

+0

Zasugerowałem-edytować znacznik jQuery, ponieważ ' $ .inArray' wraz z innymi drobnymi zmianami, jednak nie jestem do końca pewien, czy to jQuery, czy też chcesz rozwiązania jQuery (cofnij/popraw/odrzuć, jeśli tak jest) – ajax333221

Odpowiedz

10

Dzieje się tak, ponieważ szukasz innego obiektu. indexOf() używa ścisłych porównań równości (takich jak operator ===) i [3, 0] === [3, 0] zwraca wartość false.

Musisz ręcznie wyszukiwać. Oto przykład stosując bardziej ogólny indexOf() funkcję, która używa funkcji niestandardowych comparer (z poprawą sugerowane przez @ ajax333221 w komentarzach):

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

, zobacz ten [zaktualizowany przykład ] (http://jsfiddle.net/Da5GS/2/) (inne jsFiddle było złe), dlaczego powinieneś użyć 'if (w arr && comparer (arr [i], val))' – ajax333221

+0

@ ajax333221: Ahhhh, I Myślałem, że jesteś sugg estowanie za pomocą 'for ... in'. Przepraszam. Tak, jest to zdecydowanie poprawa, chociaż nie ma to znaczenia dla przypadku tego konkretnego pytania i twierdzę, że jawne ustawienie właściwości tablicy na "niezdefiniowane" wymaga kłopotów. Zaktualizuję moją odpowiedź. –

+0

dziękuję za wyjaśnienie. Działa to doskonale! –

2

Tablice są obiekty. [3, 0] nie równa się [3, 0], ponieważ są to różne obiekty. Właśnie dlatego twoja inArray się nie powiedzie.

0

To dlatego, że zarówno przy użyciu $.inArray, jak i indexOf stosuje się płytkie porównanie z użyciem ===.

Ponieważ tablica, którą przechodzisz, nie jest dokładnie taka sama w pamięci, jak w tablicy 2D, === zwraca wartość false. Musisz przeprowadzić głębokie porównanie, aby znaleźć tablicę poprawnie - od szybkiego spojrzenia na dokumenty jQuery, to nie jest dostępne.

2

Ponieważ porównujesz dwie instancje różnicy w tablicy. Porównywanie obiektów zwraca true tylko jeśli są to te same instancje, nie ma znaczenia, czy zawierają te same dane.

W twoim przypadku, można użyć tego podejścia:

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

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

Albo coś więcej Ortodox lubię:

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

Jeżeli warunek ten może być regulowana w zależności od treści tablic.

2

Dla nieskończonej zagnieżdżonego wyszukiwania:

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

Uwagi:

  • obsługuje nieskończone zagnieżdżonych tablic
  • obsługuje macierze rzadkie poprawnie
  • wykorzystuje typeof kontrole

jsFiddle demo

+0

Spędzam godziny, stwierdzając, że 'NaN! == NaN' to' true', a 'typeof null' to' "object" ' – ajax333221

0

Dlaczego nie przechowywać go proste?

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