javascript indexOf not working as expected with array

59,478

Solution 1

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.

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

Solution 2

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)

Solution 3

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

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

Solution 4

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)

Solution 5

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.

Share:
59,478

Related videos on Youtube

baixiwei
Author by

baixiwei

Postdoctoral Research Fellow at Carnegie Mellon University, Department of Psychology

Updated on February 24, 2020

Comments

  • baixiwei
    baixiwei about 4 years

    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.

    • epascarello
      epascarello over 11 years
      . Others suggested that indexOf is for strings, not arrays, but that's not true from the online docs I can find. indexOf is not supported in all browsers for Arrays. See the MDN Docs.
    • epascarello
      epascarello over 11 years
      I am getting -1 from myarray.indexOf(element) even when element appears to be in myarray. What is element? A string? A DOM Node? A number?
    • Mathletics
      Mathletics over 11 years
      BTW, you can call Array.slice() with no parameters to copy a whole array, rather than passing 0 and the length.
    • Jeremy
      Jeremy over 11 years
      What is the alert telling you idx is?
    • baixiwei
      baixiwei over 11 years
      @epascarello, element is a number.
    • baixiwei
      baixiwei over 11 years
      @Mathletics, thanks for the tip!
    • baixiwei
      baixiwei over 11 years
      @Jeremy, it's telling me that idx==-1 (the alert wouldn't fire otherwise...).
    • dpsthree
      dpsthree over 9 years
      What is the source of old array? I ran into this problem and solved it using Ajeet Shah's answer. In my problem the array to search was extracted from a JSON file. The values were quoted numbers and always displayed as numbers when debugging using console.log.
    • baixiwei
      baixiwei almost 8 years
      @Ajeet, I believe that the first batch of replies after I posted this question did not solve it. Your reply in particular does not seem to answer the question as to why IndexOf didn't work. It may be that a later reply did solve my issue but honestly it has been so long that I am not sure and don't have access to the code at this point. I feel bad about not accepting any response but I have no way to verify correctness.
  • Admin
    Admin about 10 years
    I actually encountered an issue where it wouldn't read an integer from the array even when the value matched. This solved that issue for me (a little roundabout it seems since the original way worked in console.)
  • Jeric
    Jeric almost 3 years
    This one saved my day. Thanks!