Search array for string - return -1

I have read many StackOverflow answers that tell me that in Javascript the best way to find an array for a specific string is to use indexOf()

. I have been trying to make this work for a while and I need help.

I am making a shop in a text adventure game. These are the values ​​I'm using:

Array shopCosts

:

shopCosts = [20, 25];

      

Array shopItems

:

shopItems = [["Sword", "Shield"]];

      

I dynamically create radiobooks using a loop through shopItems

:

for(var i = 0; i < array.length; i++)
{
    // Create the list item:
    var item = document.createElement('li');

    // Set its contents:
    item.appendChild(document.createTextNode(array[i] + " - " + shopCosts[i] + " Gold"));

    // Add it to the list:
    list.appendChild(item);

    var label = document.createElement("label");
    var radio = document.createElement("input");
    var text = document.createTextNode(array[i]);
    radio.type = "radio";
    radio.name = "shop";
    radio.value = array[i];
    radio.onclick = function () { addValue(this.getAttribute("value"), shopCosts, shopItems) }

    label.appendChild(radio);
    label.appendChild(text);
    document.body.appendChild(label); 
}

      

This is the part in question:

radio.onclick = function () { addValue(this.getAttribute("value"), shopCosts, shopItems) }

      

My logic was to basically assign values ​​to each dynamically created radiobout, and if it was clicked, get the value (so the name of the item you wanted to buy) and then search shopItems

for that particular row for the index value. Once I got it, I would look in the same "parallel" list shopCosts

to find the price.

I used console.log()

to see what variables were in the game. When I clicked on the switch this function is called:

function addValue(nameOfItem, shopCosts, shopItems)
{
    var positionOfShopItem = shopItems.indexOf(nameOfItem);
    console.log(positionOfShopItem);
    console..log(nameOfItem);
    console.log(shopItems);
}

      

Will of course console.log()

return the position of the named element? To prove to myself that I'm not going crazy, here's what Dev Tools says:

-1
Sword
    [Array[2]]
        0: "Sword"
        1: "Shield"

      

Sword

is clearly in the array at position 0, so why indexOf()

return -1

?

Any help is appreciated!

+3


source to share


4 answers


I understand that you have already fixed the error, but I urge you to consider a different approach to the problem. These two principles not only solve the problem in a cleaner way, but also give you a new way to think about similar problems in the future:

  • Never use parallel arrays. Use only one array of objects instead.
  • In your main loop that adds elements, put the main loop element in a function.

If you follow these two ideas, you will reap several benefits. The code becomes much simpler, easier to maintain, and you don't need to do any array lookups at all!

Each store item is packaged as one object in an array, for example:

var shopItems = [
    { name: 'Sword', cost: 20 },
    { name: 'Shield', cost: 25 }
];

      

So, if you have a link to a store item as a whole, say in a variable under the name shopItem

, then you will automatically get all your properties: shopItem.name

and shopItem.cost

. It also makes it easy to add more bits of data to a store item, for example.

var shopItems = [
    { name: 'Sword', cost: 20, dangerous: true },
    { name: 'Shield', cost: 25, dangerous: false }
];

      



and will now shopItem.dangerous

provide you with the corresponding value. All without searching for arrays.

Casting the body of the main loop into a function adds an additional benefit: inside the function, its parameters and local variables are saved every time you call the function (this is called a closure). So now you don't even need to fetch the value of the list item and search for it - you already have the corresponding shopItem

one available in your code.

Putting this together, the code might look like this:

var shopItems = [
    { name: 'Sword', cost: 20, dangerous: true },
    { name: 'Shield', cost: 25, dangerous: false }
];

var list = document.getElementById( 'list' );

for( var i = 0;  i < shopItems.length;  ++i ) {
    appendShopItem( shopItems[i] );
}

// Alternatively, you could use .forEach() instead of the for loop.
// This will work in all browsers except very old versions of IE:
// shopItems.forEach( appendShopItem );

function appendShopItem( shopItem ) {
    // Create the list item:
    var item = document.createElement( 'li' );

    // Set its contents:
    item.appendChild( document.createTextNode( 
        shopItem.name + ' - ' + shopItem.cost + ' Gold'
    ) );

    // Add it to the list:
    list.appendChild( item );

    var label = document.createElement( 'label' );
    var radio = document.createElement( 'input' );
    var text = document.createTextNode( shopItem.name );
    radio.type = 'radio';
    radio.name = 'shop';
    radio.value = shopItem.name;
    radio.onclick = function () {
        addValue( shopItem );
    };

    label.appendChild( radio );
    label.appendChild( text );
    document.body.appendChild( label ); 
}

function addValue( shopItem ) {
    console.log( shopItem );
    alert(
        shopItem.name +
        ' costs ' + shopItem.cost + ' and is ' +
        ( shopItem.dangerous ? 'dangerous' : 'not dangerous' )
    );
}

      

New violin (with the tip of the hat to Jamiec for the original violin)

As you can see, this makes the code much clearer. If you have shopItem

, you automatically have name

, cost

and any other property you want to add. And most importantly, you never need to keep track of your values ​​in the same order in two, three, or even different arrays.

+2


source


As I mentioned in my comment, its because it shopItems

does not contain a string array, it contains one element, where that one element is a string array. I suspect your code will work fine if you remove the extra square brackets



var shopItems = ["Sword", "Shield"];

      

+5


source


shopItems is an array of arrays. ShopItems index 0 contains another array which contains:

["Sword", "Shield"]

      

So when you try to find the Sword or Shield item inside shopItems, it returns -1 because it can't find either inside the array.

Edit

shopItems = [["Sword", "Shield"]];

      

For

shopItems = ["Sword", "Shield"];

      

And that will fix your problem.

0


source


I fixed it!

Removing the double square brackets led to this mess . So, as a workaround, I just added [0]

in var positionOfShopItem = shopItems.indexOf(nameOfItem);

to getvar positionOfShopItem = shopItems[0].indexOf(nameOfItem);

Thanks for helping everyone.

0


source







All Articles