Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 10 of 10
  1. #1
    New Coder
    Join Date
    Feb 2009
    Posts
    68
    Thanks
    12
    Thanked 0 Times in 0 Posts

    (Simple?) Assigning array values in a compounding loop - keep getting NaN or undefine

    Okay, I am taking a js class and there is one minor bug that is driving me crazy with this assignment.

    First, here is the code I wrote, then my question:

    Code:
    var games = ["Jacks","Chutes and Ladders","Extreme Uno","Bopit","Barbie Doll"];
    var price = [4.00,15.99,25.00,27.99,32.00];
    var inventory = [40,15,30,20,40];
    
    //I could not figure out how to make this work without assigning values first. It was giving NaN.
    var subtotal = [0,0,0,0,0];
    var qtySold = [0,0,0,0,0];
    
    function chooseItem() {
    	var answer = 0;
    	
    	while (answer != 6) {
    		var orderForm = "Choose a number below:\n";
    
    		for (var i=0; i<games.length; i++) {
    			orderForm = orderForm + (i + 1) + ".) " + games[i] + ": # in stock: " + inventory[i] + "\n";		
    		}
    		orderForm = orderForm + "6.) Show Sales Summary";
    		answer = prompt(orderForm);
    		answer = parseFloat(answer);
    		
    		if(answer != 6 && answer >= 1 && answer < games.length+1) {
    			var qty = prompt("How many " + games[answer-1] + " would you like?");			
    			qtySold[answer-1] = parseFloat(qtySold[answer-1]) + parseFloat(qty);
    			subtotal[answer-1] = qtySold[answer-1] * price[answer-1];
    		} else if (answer < 1 || answer > 6) {
    			alert("Invalid Answer");
    		} else {
    			alert("Click OK to see your summary:");
    		}
    	}
    	var summary = "Your Sales: \n";
    	for (var j=0; j<qtySold.length; j++) {
    		summary = summary + qtySold[j] + " " + games[j] + " at " + currency(price[j]) + " each for a total of " + currency(subtotal[j]) + "\n";		
    	}
    	alert(summary);
    }
    So basically, the arrays subtotal and qtySold need to retain values in case the "customer" chooses to add more of the same item in each order. What you see above works; however, when I alert the summary, it lists all of the items, even if there were none ordered. It simply says 0, but that is not what I want.

    Basically, I only want the total to reflect only the items that were actually selected.

    I do not what to do it this way:
    Code:
    var subtotal = [0,0,0,0,0];
    var qtySold = [0,0,0,0,0];
    I can effectively do this by NOT assigning any values to the qtySold array in the beginning: i.e. doing it this way:

    Code:
    var subtotal = new Array();
    var qtySold = new Array();

    The only problem is that when I do this, I get NaN at this point:
    Code:
    qtySold[answer-1] = parseFloat(qtySold[answer-1]) + parseFloat(qty);
    			subtotal[answer-1] = qtySold[answer-1] * price[answer-1];
    obviously, this is because I am referencing qtySold[answer-1]
    directly in the loop - so the first time through, there is nothing assigned.

    I can't (just before this line) assign 0 to each array item - to get it defined because if the user goes back in and adds more, it will always reset the number back to 0, which is not what I wanted.

    I tried adding an if..else statement instead, but cannot figure out how to get that to work?

    What are my options here?

    Thanks!

    Mike

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,185
    Thanks
    80
    Thanked 4,453 Times in 4,418 Posts
    Nice question.

    *Personally*, I would have simply done this, at the top of the code:
    Code:
    var subtotal = [];
    var qtySold = [];
    for ( var n = 0; n < games.length; ++n )
    {
        subtotal[n] = 0;
        qtySold[n] = 0;
    }
    But there's a certain elegance in trying to do this "on the fly".

    I can think of various ways, but maybe start with this:

    First, just do
    Code:
    var subtotal = [];
    var qtySold = [];
    at the top of the code, to ensure that the variables are arrays.

    And then maybe
    Code:
    		if(answer != 6 && answer >= 1 && answer < games.length+1) {
                            try { /* see if we can get a value from the expected array slot */
                                var ignored = subtotal[answer-1];
                            } catch( alsoIgnored ) {
                                /* assume that the error was because that slot didn't exist yet */
                                /* so initialize it */
                                subtotal[answer-1] = 0;
                                qtySold[answer-1] = 0;
                            }
    			var qty = prompt("How many " + games[answer-1] + " would you like?");			
    			qtySold[answer-1] = parseFloat(qtySold[answer-1]) + parseFloat(qty);
    			subtotal[answer-1] = qtySold[answer-1] * price[answer-1];
                     ...
    ??
    Last edited by Old Pedant; 09-25-2011 at 03:05 AM.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #3
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,185
    Thanks
    80
    Thanked 4,453 Times in 4,418 Posts
    Personally, I would have done this:
    Code:
    // create a constructor for a Game object:
    function Game( Name, Price, Qty )
    {
        this.name = Name;
        this.price = Price;
        this.qty = Qty;
        this.qtySold = 0;
        this.subtotal = 0.0;
    }
    var games = [
        null, /* so we don't have to keep using answer-1! */
        new Game("Jacks",4.00,40),
        new Game("Chutes and Ladders",15.99,15),
        new Game("Extreme Uno",25.00,30),
        new Game("Bopit",27.99,20),
        new Game("Barbie Doll",32.00,49)
       ];
    And then that same part of your code would look like:
    Code:
    	if( answer >= 1 && answer < games.length) 
            {
                var game = games[answer]; // see?  no -1 needed because of the null
                var buy = prompt("How many " + game.name + " would you like?");			
                game.qtySold += parseInt(buy); // int because you can't buy half a game!
                game.subtotal = game.qtySold * game.price;
                     ...
    But don't turn that in for homework! It's way beyond where you are now. Just think about it for the future.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #4
    New Coder
    Join Date
    Feb 2009
    Posts
    68
    Thanks
    12
    Thanked 0 Times in 0 Posts
    HaHa! Yeah, I wouldn't turn that in for my homework! It's actually not that far ahead of where we are (and the instructor pretty much let's us up the ante, if you will, if we have the ability and time). I have found that I have quite a bit more experience than anyone else in the class and do way more than is expected on the assignments (sometimes to my detriment); I have been designing sites for the past 6 or 7 years and while I have used some JS in the past, never really "understood" it proficiently. Plus I needed one more credit to finish my B.S. in CMIS.

    Anyway, I initially started with using a constructor, but realized when it came time for the "ordering" aspects (at least the way he wanted us to do it) I was so lost. The starting examples he gave were using arrays so I just went with that. Your example makes it really clear though and I am tempted to start over - haha. But I won't because this is all due tomorrow. I already drove into the mud, might as well continue on.

    I figured out what is probably a horribly non-graceful way to do it, but it does work.

    I was using Firebug and realized that just before this code ran that each of the indexes were listed as undefined. So, just before this code, I check to first see if the index is undefined. If so, assign it 0 so that the math will result in a number (instead of NaN). If the index is NOT undefined, continue on as usual.

    Here is what I came up with:

    Code:
    var subtotal = new Array();
    var qtySold = new Array();
    
    ....
    
    if(answer != 6 && answer >= 1 && answer < games.length+1) {
    			var qty = prompt("How many " + games[answer-1] + " would you like?");
                            //see, here is the ugly stuff - but at least I know that! I am too much of a perfectionist to do this in practice.
    			if (typeof(qtySold[answer-1]) === "undefined") {
    				qtySold[answer-1] = 0;
    			} else {
    				qtySold[answer-1] = qtySold[answer-1];				
    			}
    			qtySold[answer-1] = parseFloat(qtySold[answer-1]) + parseFloat(qty);
    			subtotal[answer-1] = qtySold[answer-1] * price[answer-1];
    		} else if (answer < 1 || answer > 6) {
    			alert("Invalid Answer");
    		} else {
    			alert("Click OK to see your summary:");
    		}

    Thanks again for your help. I am not the type to just come on the forums and get answers without even trying on my own first. In fact, I only come on at last resort, like today, but I am sure you will see me around for the next 10 weeks!

    Have a good weekend!

    Mike

  • #5
    New Coder
    Join Date
    Feb 2009
    Posts
    68
    Thanks
    12
    Thanked 0 Times in 0 Posts
    OK, actually, I spoke too soon. If I choose only the first item and the second item (or any consecutive indexes) , it works fine. However, if I choose say the first and third, then I again the NaN in the summary.

    I think at this point, I am just going to not push the issue - go ahead an assign the indexes 0 from the start and take the few points off, knowing this is not the best solution anyway.

    Oh well, at least I learned how to check if an index is undefined!

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,185
    Thanks
    80
    Thanked 4,453 Times in 4,418 Posts
    I really don't see what's wrong with my first suggestion: Init the arrays to the same size as the Games array. In most any other language, that's what you'd have to do. JS is too flexible, allowiing you to assign to array elements that don't yet exist.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #7
    New Coder
    Join Date
    Feb 2009
    Posts
    68
    Thanks
    12
    Thanked 0 Times in 0 Posts
    Actually, you are right - your first suggestion does work but the only real difference is that it looks better than [0,0,0,0,0]. However, it still does not solve the problem of having the summary have "0" entries for items not selected.

    Either way, I just left it how it was. I went about 500% above and beyond what was required for this assignment anyway and the instructor is perfectly fine with the way I have it.

    In hindsight, I have learned that #1 - this would have been better with objects and a constructor (though I am not as comfortable with those yet), and #2 - the reason that I am getting the "0" entries at the summary screen is because you cannot have an array that looks like this: [15, null, 8, null, null, 7). Or is that wrong? It seems that the reason this happens is that when I select an item that is in the [0] position and then another at the [2] position, it automatically creates the [1] position and assigns "0" as the value.

    I could probably come up with some overly-complicated code in the creation (through concatenation) that leaves out any of the array items that are ==0. (i.e. in the following code

    Code:
    var summary = "Your Sales: \n";
    
    for (var j=0; j<qtySold.length; j++) {
    summary = summary + qtySold[j] + " " + games[j] + " at " + currency(price[j]) + 
    " each for a total of " + currency(subtotal[j]) + "\n";		
    	}
    	alert(summary);
    	alert("The total cost of your items is " + currency(total) + 
                   "\nThank you for shopping with us!!");
    }
    Thanks again for your help!

    Mike

  • #8
    New Coder
    Join Date
    Feb 2009
    Posts
    68
    Thanks
    12
    Thanked 0 Times in 0 Posts
    Wowww - I cannot believe how easy that was! Forums are good because sometimes I figure things out by simply typing the logic out! All I had to do was add an if statement and now the summary ONLY shows what has been selected!

    Success!!

    Code:
    var summary = "Your Sales: \n";
    for (var j=0; j<qtySold.length; j++) {
    	if (qtySold[j] != 0) {
    	summary = summary + qtySold[j] + " " + games[j] + " at " + 
                 currency(price[j]) + " each for a total of " + currency(subtotal[j]) + "\n";
    		}
    	}
    	alert(summary);
    	alert("The total cost of your items is " + currency(total) + "\nThank you for shopping with us!!");
    }
    Thanks again!

    Mike

  • #9
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,185
    Thanks
    80
    Thanked 4,453 Times in 4,418 Posts
    Your solution clearly works, but...
    you cannot have an array that looks like this: [15, null, 8, null, null, 7]. Or is that wrong?
    Wrong. Sure you can. And it's actually a really good technique.

    So you could have done
    Code:
    var subtotal = [];
    var qtySold = [];
    for ( var n = 0; n < games.length; ++n )
    {
        subtotal[n] = null;
        qtySold[n] = null;
    }
    ...
    		if(answer != 6 && answer >= 1 && answer < games.length+1) {
    			var qty = prompt("How many " + games[answer-1] + " would you like?");			
                            if ( qtysold[answer-1] == null ) qtysold[answer-1] = 0;
    			qtySold[answer-1] += parseInt(qty);
    			subtotal[answer-1] = qtySold[answer-1] * price[answer-1];
                     ...
    or you could do it all in one line
    Code:
             qtySold[answer-1] = (qtySold[answer-1]==null ? 0 : qtySold[answer-1]) + parseInt(qty);
    
    NOT suggesting any of this. Just pointing out that null array elements can actually be useful.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #10
    New Coder
    Join Date
    Feb 2009
    Posts
    68
    Thanks
    12
    Thanked 0 Times in 0 Posts
    Thanks for that. I thought that it sounded wrong once I typed it. The problem then was assigning an initial value to the array item before trying to add a quantity to it. That is why I was getting NaN I believe.

    Either way, I am finished with this one and will pocket this info for future use. I really appreciate your help on this and hopefully others will be helped by it in the future.

    New assignments start this weekend, so I am sure I will be around

    Mike


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •