javascript indexOf not working as expected with array

I am getting -1 from myarray.indexOf(element) even when element appears to be in myarray.

Here’s some code snippets:

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

The alert shows me that nds does indeed contain el but the alert should only fire when idx==-1, which should only be true when nds does not contain el.

I know I haven’t given enough information to determine the specific issue in my case, but maybe someone can tell me some general reasons which might cause this behavior?

Responses to a similar question suggested using jQuery inArray() instead of indexOf, but I want to know why indexOf doesn’t work. Others suggested that indexOf is for strings, not arrays, but that’s not true from the online docs I can find.

Use

nds.indexOf(parseInt(el,10)) 

where nds is an array and el is a number (or supposed to be a number)

Edit:

From msdn:

JavaScript is a loosely typed language, which means you do not declare
the data types of variables explicitly. In many cases JavaScript
performs conversions automatically when they are needed. For example,
if you add a number to an item that consists of text (a string), the
number is converted to text.

And I guess such conversion was the reason of indexOf returning -1 because one of your array contained number and other contained string.

Read More:   Capturing the "scroll down" event?

For example:

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

Below is my attempt to answer your questions:

Why indexOf() does not work?

It does work and I guess it worked in your case too.
It returned -1 when el string, e.g "100", was not found in an array of numbers, e.g. nds=[100,200] which is true. Because "100" string is not same as 100 number.

Does indexOf() work with strings, array, etc?

Yes, indexOf() works with array (of number, string, or any object), as well as with string. But you have to make sure to check with same types.

What does parseInt() do?

To avoid unintended comparison of a number with a string, we can use parseInt(), for example parseInt("123", 10) returns the number 123.

The second argument 10 is called radix. A number (from 2 to 36) that represents the numeral system to be used.

Summary:

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

To see all of above in action:

check the below code snippet but be aware of alert(); and console.log(); when you run it.

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

indexOf does work and does do what you say it does.

Read More:   How to check whether a string contains a substring in JavaScript?

For example (to demonstrate from a console):

> 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

If you’re getting this error, it might mean you’ve mixed up source and destination (the array before the dot is the one being searched), or you have another subtle programming error (like you aren’t comparing the array you think you’re comparing).

When you use indexOf(value) on an Array, it returns you the index of the value in the array.

> 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

You should check what you get from el with a typeof(el)

Taking the top example:

where you have idx=nds.indexOf(el)

replace it with idx=nds.indexOf(''+el+'')

It solved a similar problem for me within the thing I’m working on, but I stumbled on it messing around looking for a solution.

Whether it’s stable in all circumstances is something I can’t answer.

If your search array contained numbers, and you want to search for items like 2 or "2"

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

This works (Add plus)

nds.indexOf(+el)


The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Similar Posts