javascript indexOf не работает должным образом с массивом

Я получаю -1 от myarray.indexOf(element), даже если элемент находится в моем массиве.

Вот несколько фрагментов кода:

function createChangeRecord( old_array, new_array ) {
    var nds = new_array.slice(0,new_array.length);
    var el, idx;
    if (...) {
        ...
    } else if ( old_array.length==new_array.length ) {
        for ( var i=0; i<old_array.length; i++ ) {
            el = old_array[i];
            idx = nds.indexOf(el);
            if ( idx!=(-1) ) {
                ...
            } else {
                var a = "el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + nds.indexOf(el);
                alert( a );
                ...
            }
        }
        ...
    }
    ...
}

Предупреждение показывает мне, что nds действительно содержит el, но предупреждение должно срабатывать только тогда, когда idx==-1, что должно быть правдой только тогда, когда nds не содержит el.

Я знаю, что не предоставил достаточно информации, чтобы определить конкретную проблему в моем случае, но, может быть, кто-нибудь может назвать мне некоторые общие причины, которые могут вызвать такое поведение?

В ответах на аналогичный вопрос предлагалось использовать jQuery inArray() вместо indexOf, но я хочу знать, почему indexOf не работает. Другие предположили, что indexOf предназначен для строк, а не для массивов, но это неверно из онлайн-документов, которые я могу найти.


person baixiwei    schedule 08.01.2013    source источник
comment
<я>. Другие предположили, что indexOf предназначен для строк, а не для массивов, но это неверно из онлайн-документов, которые я могу найти. indexOf не поддерживается во всех браузерах для массивов. См. документы MDN.   -  person epascarello    schedule 08.01.2013
comment
Я получаю -1 из myarray.indexOf(element), даже если элемент находится в myarray. Что такое element? Строка? DOM-узел? Число?   -  person epascarello    schedule 08.01.2013
comment
Кстати, вы можете вызвать Array.slice() без параметров, чтобы скопировать весь массив, а не передавать 0 и length.   -  person Mathletics    schedule 09.01.2013
comment
О чем предупреждает вас idx?   -  person Jeremy    schedule 09.01.2013
comment
@epascarello, элемент — это число.   -  person baixiwei    schedule 10.01.2013
comment
@Mathletics, спасибо за совет!   -  person baixiwei    schedule 10.01.2013
comment
@ Джереми, он говорит мне, что idx==-1 (иначе предупреждение не сработает...).   -  person baixiwei    schedule 10.01.2013
comment
Каков источник старого массива? Я столкнулся с этой проблемой и решил ее, используя ответ Аджита Шаха. В моей проблеме массив для поиска был извлечен из файла JSON. Значения были указаны в кавычках и всегда отображались как числа при отладке с помощью console.log.   -  person dpsthree    schedule 28.01.2015
comment
@Ajeet, я считаю, что первая партия ответов после того, как я опубликовал этот вопрос, не решила его. В частности, ваш ответ, похоже, не отвечает на вопрос, почему IndexOf не работает. Возможно, более поздний ответ действительно решил мою проблему, но, честно говоря, это было так давно, что я не уверен и не имею доступа к коду на данный момент. Я сожалею о том, что не принимаю никаких ответов, но у меня нет возможности проверить правильность.   -  person baixiwei    schedule 25.05.2016


Ответы (5)


Использовать

nds.indexOf(parseInt(el,10)) 

где nds — массив, а el — число (или должно быть числом)

Изменить:

Из msdn:

JavaScript — это язык со свободной типизацией, что означает, что вы не объявляете явно типы данных переменных. Во многих случаях JavaScript выполняет преобразования автоматически, когда они необходимы. Например, если вы добавляете число к элементу, состоящему из текста (строки), число преобразуется в текст.

И я предполагаю, что такое преобразование было причиной того, что indexOf возвращает -1, потому что один из ваших массивов содержал число, а другой - строку.

Например:

old_array = ["10", "20", "30"];
new_array = [10, 20, 30];

Ниже моя попытка ответить на ваши вопросы:

Почему indexOf() не работает?

Это работает, и я думаю, что это сработало и в вашем случае. Он возвращал -1, когда строка el, например "100", не была найдена в массиве чисел, например. nds=[100,200] что верно. Потому что строка "100" не совпадает с числом 100.

Работает ли indexOf() со строками, массивами и т. д.?

Да, indexOf() работает как с массивом (числом, строкой или любым объектом), так и со строкой. Но вы должны убедиться, что проверили те же типы.

Что делает parseInt()?

Чтобы избежать непреднамеренного сравнения числа со строкой, мы можем использовать parseInt(), например, parseInt("123", 10) возвращает число 123.

Второй аргумент 10 называется основанием счисления. Число (от 2 до 36), представляющее используемую систему счисления.

Резюме:

> "javascript is awesome".indexOf('v')
2
> [10, 20, 30].indexOf("20")
-1
> [10, 20, 30].indexOf(20)
1
> [10, 20, 30].indexOf( parseInt("20", 10) ) 
1
> typeof (100)
number
> typeof ("100")
string
> typeof( parseInt( "100", 10))
number
> parseInt( "100", 10)
100
> parseInt("100", 2)
4
> parseInt(11.3, 10)
11
> parseInt(11.3, 2)
3
> [10.3, 11.3, 12.3, 11].indexOf( parseInt(11.3, 10) )
3

Чтобы увидеть все вышеперечисленное в действии:

проверьте приведенный ниже фрагмент кода, но помните о alert(); и console.log(); при его запуске.

function createChangeRecord( old_array, new_array ) {

    var nds = new_array.slice( 0, new_array.length ); // this seems to be redundant
    var el, idx, msg;
    
    if ( old_array.length == new_array.length ) {
        for ( var i=0; i<old_array.length; i++ ) {

            el = old_array[i];
            idx = nds.indexOf(el);

            if ( idx != -1 ) {
                msg = "Found: el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + idx + "\n typeof el: " + (typeof el) + "; typepf nds[" + i + "]: " + (typeof nds[i]);
            } else {
                msg = "Not Found: el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + idx + "\n typeof el: " + (typeof el) + "; typepf nds[" + i + "]: " + (typeof nds[i]);
            }

            console.log( msg );
            alert( msg );
        }
    }
    else {
        var err = 'Array lengths are not same';
        console.log( err );
        alert( err );
    }
}

// this will work
var old_array_g = [ 10, 20 ];
var new_array_g = [ 10, 20 ];
createChangeRecord( old_array_g, new_array_g );

// this will not work
var old_array_g = [ "10", "20" ];
var new_array_g = [ 10, 20 ];
createChangeRecord( old_array_g, new_array_g );

// Yes: indesOf works with strings too

var withStrings = "'javascript is awesome'.indexOf('v'): " + "javascript is awesome".indexOf('v');
console.log( withStrings );
alert( withStrings );


// parseInt() returns a number or say integer
var usingParse = "typeof(123): " + typeof( 123 ) + "; typeof( parseInt('123', 10) ): " + typeof ( parseInt('123', 10) ) + "; typeof ('123'): " + typeof('123');
console.log( usingParse );
alert( usingParse );

// parseInt() with base 2
var parseBase2 = "parseInt( '100', 2 ): " + parseInt('100', 2) + "; parseInt( '100' , 10): " + parseInt('100', 10);
console.log( parseBase2 );
alert( parseBase2 );

person Ajeet Shah    schedule 20.10.2013
comment
На самом деле я столкнулся с проблемой, когда он не читал целое число из массива, даже если значение совпадало. Это решило эту проблему для меня (кажется, немного окольным путем, поскольку исходный способ работал в консоли). - person ; 14.03.2014

indexOf действительно работает и делает то, что вы говорите.

Например (для демонстрации из консоли):

> a = [1,2,3,4,5,6,7,8];
  [1, 2, 3, 4, 5, 6, 7, 8]
> b = a.slice(0,a.length);
  [1, 2, 3, 4, 5, 6, 7, 8]
> b.indexOf(a[4])
  4

Если вы получаете эту ошибку, это может означать, что вы перепутали источник и место назначения (массив перед точкой ищется) или у вас есть другая тонкая ошибка программирования (например, вы не сравниваете массив, который, по вашему мнению, вы сравниваете).

person Plynx    schedule 08.01.2013

Когда вы используете indexOf(value) в массиве, он возвращает вам индекс value в массиве.

> var testArray = ["a","b","c"];
> testArray.indexOf(1)
-1
> testArray.indexOf("b")
1
> testArray.indexOf("c")
2
> testArray = [10,12,3];
> testArray.indexOf(12)
1

Вы должны проверить, что вы получаете от el с помощью typeof(el)

person Finickyflame    schedule 08.01.2013

Возьмем верхний пример:

где у вас есть idx=nds.indexOf(el)

замените его на idx=nds.indexOf(''+el+'')

Он решил аналогичную проблему для меня в том, над чем я работаю, но я наткнулся на него, ища решение.

Я не могу ответить, стабилен ли он при любых обстоятельствах.

person Howard    schedule 14.03.2019
comment
Этот спас мой день. Спасибо! - person Jeric; 28.07.2021

Если ваш массив поиска содержит числа, и вы хотите найти такие элементы, как 2 или "2"

nds = [1, 2, 3, 4, 5];

Это работает (добавьте плюс)

nds.indexOf(+el)
person user2511140    schedule 24.02.2020