2012-04-21 2 views
8

У меня есть массив с вложенными массивами, выглядит следующим образом:Javascript IndexOf для массива массивов не находя массив

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

Когда я пытаюсь найти, если массив tw содержит принятый в массиве, я всегда получаю результат -1.

Например:

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

возвращается -1, даже если первый объект в массиве [3,0] Как я могу узнать, если определенный массив массивов содержится в моем массиве?

О, и я тестировал его только на IE9.

+2

[IndexOf сравнивает searchElement к элементам массива, используя строгое равенство -то же метод, используемый ===, или тройных равных, оператор] (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf) - Я не вижу, что массив является целевым значением в [inarray] (http://api.jquery.com/jQuery.inArray/) либо – mplungjan

+0

Я предложил изменить тег jQuery, поскольку ' $ .inArray' вместе с другими незначительными изменениями, однако я не совсем уверен, что это jQuery или вам нужны решения jQuery (отменить/улучшить/отклонить, если это так) – ajax333221

ответ

10

Это потому, что вы ищете другой объект. indexOf() использует строгое сравнение равенства (например, оператор ===) и [3, 0] === [3, 0] возвращает false.

Необходимо выполнить поиск вручную. Вот пример, используя более общую indexOf() функцию, которая использует пользовательскую функцию компаратора (с улучшением предложенного @ ajax333221 в комментариях):

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

<удаленный мой спам>, см. этот [обновленный пример ] (http://jsfiddle.net/Da5GS/2/) (другой jsFiddle был неправильным), почему вы должны использовать 'if (i в arr && comparer (arr [i], val))' – ajax333221

+0

@ ajax333221: Ahhhh, I подумал, что вы предлагаете с использованием 'for ... in'. Сожалею. Да, это определенно улучшение, хотя для случая этого конкретного вопроса не имеет значения, и я бы сказал, что явное указание свойства массива 'undefined' вызывает проблемы. Я уточню свой ответ. –

+0

Благодарим вас за разъяснение. Это прекрасно работает! –

2

Массивы объекты. [3, 0] не равно [3, 0], поскольку они являются разными объектами. Вот почему ваш inArray терпит неудачу.

0

Это потому, что $.inArray и indexOf оба используют мелкое сравнение с использованием ===.

Поскольку массив, который вы передаете, имеет значение indexOf, не то же самое в памяти, что и в вашем 2D-массиве, === возвращает false. Вам нужно будет сделать глубокое сравнение, чтобы найти массив правильно - быстро взглянув на документы jQuery, этого там нет.

2

Потому что вы сравниваете два разностных экземпляра массива. Сравнение объектов возвращает true, только если они являются одним и тем же экземпляром, не имеет значения, содержат ли они одни и те же данные.

В вашем случае, вы могли бы использовать этот подход:

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

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

Или что-то более ORTODOX нравится:

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

Если условие может быть скорректирована в зависимости от содержания массивов.

2

Для бесконечного вложенного поиска:

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

Примечания:

  • поддерживает бесконечные вложенные массивы
  • обрабатывает разреженные массивы правильно
  • использует typeof проверки

jsFiddle demo

+0

Я трачу часы, выясняя, что 'NaN! == NaN' является' истинным', а 'typeof null' является' "объектом" ' – ajax333221

0

Почему бы не держать его просто?

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; 
} 
Смежные вопросы