Using counter in variable name - javascript

This is what I have currently but I cant get v(i) to behave the same as v1. What am I doing wrong?
I've also tried the piece below which also did not work.
var x = "v" + i;
alert(x);
My main problem is the following:
var v1 = document.getElementById("thing1").innerHTML; // = 100
var v2 = document.getElementById("thing2").innerHTML; // = 150
var v3 = document.getElementById("thing3").innerHTML; // = 200
for (i = 0; i < 4; i++) {
if ( v(i) != ""){
alert(v(i));
}
}
Thanks in advance:)

What you are trying to do is not easily accomplished. You would have to assign the variable to the window object and then print it from there.
A much better solution is to use your own object or array to handle this:
var v1 = document.getElementById("thing1").innerHTML; // = 100
var v2 = document.getElementById("thing2").innerHTML; // = 150
var v3 = document.getElementById("thing3").innerHTML; // = 200
var array = [v1,v2,v3];
for (i = 0; i < 4; i++) {
if ( array[i] != ""){
alert(array[i]);
}
}

All global variables are properties of window object you could use window['v'+ i] or this['v'+ i] to create them.
But this is very bad pattern consider using object instead.

What you are trying to do is get an interpolated variable name, which is not possible in javascript the way you do it.
You can do this using this['v'+i] or window['v'+i] which are both bad ideas in the global scope.
v(i) actually means: run function v(...) with parameter i
If i would write your example code in easy to understand javascript, i would come up with this:
for(var i = 1; i <= 4; i++)
{
var html = document.getElementById('thing'+i).innerHTML;
alert(html);
}
If you want your values in an array, in a way that you don't write the same code 6 times:
var ids = ['thing1','thing2','thing3','thing4'];
// es5
var values = [];
for(var i = 0; i < ids.length; i++)
{
var html = document.getElementById( ids[i] ).innerHTML;
values.push( html );
}
// values now contains all the values of the elements
// OR es 6
var values = ids.map(function(id) { return document.getElementById(id).innerHTML; });
// or
var values = ids.map(id => document.getElementById(id).innerHTML);

You could use an array without using single variables and loop it.
var array = [
'100', // document.getElementById("thing1").innerHTML,
'150', // document.getElementById("thing2").innerHTML,
'200' // document.getElementById("thing3").innerHTML
],
i;
for (i = 0; i < array.length; i++) {
if (array[i] !== "") {
console.log(array[i]);
}
}
If you need some keys, you could use an object.
var object = {
v1: '150', // document.getElementById("thing1").innerHTML,
v2: '200', // document.getElementById("thing2").innerHTML,
v3: '250', // document.getElementById("thing3").innerHTML
},
i;
for (i = 1; i <= 3; i++) {
if (object['v' + i] !== "") {
console.log(object['v' + i]);
}
}

Related

Array equals itself plus number = NaN

I must be doing something stupid. The array newArea needs to add up data from all regions, i.e. be global. Regions are represented by variable p. But when I try to get newArea array to add to itself, e.g. newArea[p] += otherArray, it outputs NaNs. Even newArea[p] += 1 outputs NaNs.
Can anyone spot what I'm doing wrong? It's driving me mad and I'm working to a deadline.
mm=0
var maxVolume = 0;
var tempCAGR = 0;
var maxCAGR = 0;
var newArray = [];
var newRegions = [];
var newConsValues = [];
var newArea = [];
for (var p=0; p<arrayRef[mm].length; p++) {//9 regions
newArray[p] = [];
for (var q=0; q<arrayRef[mm][p].length; q++) {//4 scenarios
newArea[q] = [];
if (q==0) {
newRegions.push(arrayRef[mm][p][q][0]);
newConsValues.push(arrayRef[mm][p][q][1]);
}
for (var r=0; r<dates.length; r++) {//time
//console.log('p: '+p+', q: '+q+', r: '+r);
if (p==0) {
newArea[q][r] = 1;
} else {
newArea[q][r] += 1;
}
}
arrayRef[mm][p][q].shift();
tempCAGR = Math.pow(( arrayRef[mm][p][q][len] / arrayRef[mm][p][q][1] ),(1/len))-1;
//console.log(newRegions[p]+', num: '+arrayRef[mm][p][q][len-1]+', denom: '+arrayRef[mm][p][q][0]+', len: '+len+', cagr: '+tempCAGR);
newArray[p][q] = tempCAGR;
maxCAGR = Math.max(maxCAGR,tempCAGR);
}
}
console.log(newArea);
You are cleaning the array in newArea everytime you loop through it:
...loop q ...
newArea[q] = []; // <-- resets the array at q pos
... loop r ...
if (p==0) {
newArea[q][r] = 1;
} else {
newArea[q][r] += 1;
}
So when p === 0 it will fill an array at q pos of your newArea array. However, next iteration of p will clear them out, so there's nothing there to sum.
You probably want to keep the old array or create a new one if there isn't one.
newArea[q] = newArea[q] || [];
It looks like you do not have the variable initialised. With adding something to undefined, you get NaN.
You can change the art of incrementing with a default value:
if (p == 0) {
newArea[q][r] = 1;
} else {
newArea[q][r] = (newArea[q][r] || 0) + 1;
}

If value == 1 then get the next value in the array

var countries = [1,"DK",2,"USA",3,"Sweden",];
var languages = [2,"EN",3,"Swedish",1,"Danish"];
var population = [2,"300000000",1,"6000000",3,"8000000"];
In javascript, is there a way to look for a value in an array, for example if the value is 1, then take the next value in the array. Here it would be DK, Danish and 6000000.
I have this but think it should be way to do it more simple
for(var i = 1 ; i < countries.length; i = i+2){
var countryName = countries[i];
var countryId = countries[i-1];
for(var j = 0; j < languages.length; j = j+2){
if(languages[j] == countryId){
var positionSpokenLanguage = j + 1;
var spokenLanguage = languages[positionSpokenLanguage];
}
if(population[j] == countryId){
var positionPopulation = j + 1;
var totalPopulation = population[positionPopulation];
}
}
var message = "In "+countryName+" people speak "+spokenLanguage+
" and there are "+totalPopulation+" inhabitatns";
console.log(message);
}
As you are actually looking for a value in every other item in the array, there is no built in method for that.
If you know that the value is in the array, you can just loop until you find it:
var index = 0;
while (countries[index] != 1) index += 2;
var value = countries[index + 1];
Your data has an unintuitive format, which makes it a bit awkward to work with. If possible you should use a data format where you don't mix keys with values, for example an object:
var countries = { 1: "DK", 2: "USA", 3: "Sweden" };
Then you can just get the value using the key:
var value = countries[1];

trouble filling bidimensional Array with objects in JavaScript

I've got this array in a "global" position (out of every function in my doc).
var arrayBidimensional;
Then, i'm trying to filling it like this:
var objetoLetra = new objectLetter("","","","","");
arrayBidimensional=new Array(tamano);
for (i=0; i <tamano; i++)
arrayBidimensional[i]=new Array(tamano);
var random = Math.floor((Math.random()*26)+0);
for (var i = tamano - 1; i >= 0; i--)
{
for (var j = tamano - 1; j >= 0; j--)
{
random = Math.floor((Math.random()*26)+0);
objetoLetra.letra = letras[random];
objetoLetra.letraposx = j;
objetoLetra.letraposy = i;
objetoLetra.formapalabra = "no";
objetoLetra.iden = j+""+i;
arrayBidimensional[i][j] = objetoLetra;
}
}
so when i tried to reach to this array in some position like array[X][X]
all i've got is the very first position. Example: if the first position (That is 0,0) is "A", then, the entire array got "A" on every single position, even if it is [(max position), (max position)].
How do i see that?, well, i'm building a Table with td-s like this:
'<td width="30">'+arrayBidimensional[i][j].letra+'</td>'
Then, the entire table is just a lot of "A" every single cell... So... What i am doing wrong?
Please and thank you!
You need to create a new objectLetter for each location in the array:
arrayBidimensional = new Array(tamano);
for (i=0; i < tamano; i++) {
arrayBidimensional[i] = new Array(tamano);
}
for (var i = tamano - 1; i >= 0; i--)
{
for (var j = tamano - 1; j >= 0; j--)
{
var objetoLetra = new objectLetter("","","","","");
var random = Math.floor((Math.random()*26)+0);
objetoLetra.letra = letras[random];
objetoLetra.letraposx = j;
objetoLetra.letraposy = i;
objetoLetra.formapalabra = "no";
objetoLetra.iden = j+""+i;
arrayBidimensional[i][j] = objetoLetra;
}
}
Here's what a Multidimensional Array should look like in JavaScript:
var multi = [['String', 0, 'something else'],['another String', 42, 'whatever']];
or
var multi = new Array(new Array('String', 0, 'something else'), new Array('another String', 42, 'whatever'));
console.log(multi[1][2]); // 'whatever'
console.log(multi[0][1]); // 0

Randomly generate objects in canvas without duplicate or overlap

How do I generate objects on a map, without them occupying the same space or overlapping on a HTML5 Canvas?
X coordinate is randomly generated, to an extent. I thought checking inside the array to see if it's there already, and the next 20 values after that (to account for the width), with no luck.
var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function(){
var positiony = 0, type;
for (var i = 0; i < nrOfPlatforms; i++) {
type = ~~(Math.random()*5);
if (type == 0) type = 1;
else type = 0;
var positionx = (Math.random() * 4000) + 500 - (points/100);
var duplicatetest = 21;
for (var d = 0; d < duplicatetest; d++) {
var duplicate = $(jQuery.inArray((positionx + d), platforms));
if (duplicate > 0) {
var duplicateconfirmed = true;
}
}
if (duplicateconfirmed) {
var positionx = positionx + 20;
}
var duplicateconfirmed = false;
platforms[i] = new Platform(positionx,positiony,type);
}
}();
I originally made a cheat fix by having them generate in an area roughly 4000 big, decreasing the odds, but I want to increase the difficulty as the game progresses, by making them appear more together, to make it harder. But then they overlap.
In crude picture form, I want this
....[]....[].....[]..[]..[][]...
not this
......[]...[[]]...[[]]....[]....
I hope that makes sense.
For reference, here is the code before the array check and difficulty, just the cheap distance hack.
var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function(){
var position = 0, type;
for (var i = 0; i < nrOfPlatforms; i++) {
type = ~~(Math.random()*5);
if (type == 0) type = 1;
else type = 0;
platforms[i] = new Platform((Math.random() * 4000) + 500,position,type);
}
}();
EDIT 1
after some debugging, duplicate is returning as [object Object] instead of the index number, not sure why though
EDIT 2
the problem is the objects are in the array platforms, and x is in the array object, so how can I search inside again ? , that's why it was failing before.
Thanks to firebug and console.log(platforms);
platforms = [Object { image=img, x=1128, y=260, more...}, Object { image=img, x=1640, y=260, more...} etc
You could implement a while loop that tries to insert an object and silently fails if it collides. Then add a counter and exit the while loop after a desired number of successful objects have been placed. If the objects are close together this loop might run longer so you might also want to give it a maximum life span. Or you could implement a 'is it even possible to place z objects on a map of x and y' to prevent it from running forever.
Here is an example of this (demo):
//Fill an array with 20x20 points at random locations without overlap
var platforms = [],
platformSize = 20,
platformWidth = 200,
platformHeight = 200;
function generatePlatforms(k) {
var placed = 0,
maxAttempts = k*10;
while(placed < k && maxAttempts > 0) {
var x = Math.floor(Math.random()*platformWidth),
y = Math.floor(Math.random()*platformHeight),
available = true;
for(var point in platforms) {
if(Math.abs(point.x-x) < platformSize && Math.abs(point.y-y) < platformSize) {
available = false;
break;
}
}
if(available) {
platforms.push({
x: x,
y: y
});
placed += 1;
}
maxAttempts -= 1;
}
}
generatePlatforms(14);
console.log(platforms);
Here's how you would implement a grid-snapped hash: http://jsfiddle.net/tqFuy/1/
var can = document.getElementById("can"),
ctx = can.getContext('2d'),
wid = can.width,
hei = can.height,
numPlatforms = 14,
platWid = 20,
platHei = 20,
platforms = [],
hash = {};
for(var i = 0; i < numPlatforms; i++){
// get x/y values snapped to platform width/height increments
var posX = Math.floor(Math.random()*(wid-platWid)/platWid)*platWid,
posY = Math.floor(Math.random()*(hei-platHei)/platHei)*platHei;
while (hash[posX + 'x' + posY]){
posX = Math.floor(Math.random()*wid/platWid)*platWid;
posY = Math.floor(Math.random()*hei/platHei)*platHei;
}
hash[posX + 'x' + posY] = 1;
platforms.push(new Platform(/* your arguments */));
}
Note that I'm concatenating the x and y values and using that as the hash key. This is to simplify the check, and is only a feasible solution because we are snapping the x/y coordinates to specific increments. The collision check would be more complicated if we weren't snapping.
For large sets (seems unlikely from your criteria), it'd probably be better to use an exclusion method: Generate an array of all possible positions, then for each "platform", pick an item from the array at random, then remove it from the array. This is similar to how you might go about shuffling a deck of cards.
Edit — One thing to note is that numPlatforms <= (wid*hei)/(platWid*platHei) must evaluate to true, otherwise the while loop will never end.
I found the answer on another question ( Searching for objects in JavaScript arrays ) using this bit of code to search the objects in the array
function search(array, value){
var j, k;
for (j = 0; j < array.length; j++) {
for (k in array[j]) {
if (array[j][k] === value) return j;
}
}
}
I also ended up rewriting a bunch of the code to speed it up elsewhere and recycle platforms better.
it works, but downside is I have fewer platforms, as it really starts to slow down. In the end this is what I wanted, but its no longer feasible to do it this way.
var platforms = new Array();
var nrOfPlatforms = 7;
platformWidth = 20,
platformHeight = 20;
var positionx = 0;
var positiony = 0;
var arrayneedle = 0;
var duplicatetest = 21;
function search(array, value){
var j, k;
for (j = 0; j < array.length; j++) {
for (k in array[j]) {
if (array[j][k] === value) return j;
}
}
}
function generatePlatforms(ind){
roughx = Math.round((Math.random() * 2000) + 500);
type = ~~(Math.random()*5);
if (type == 0) type = 1;
else type = 0;
var duplicate = false;
for (var d = 0; d < duplicatetest; d++) {
arrayneedle = roughx + d;
var result = search(platforms, arrayneedle);
if (result >= 0) {
duplicate = true;
}
}
if (duplicate = true) {
positionx = roughx + 20;
}
if (duplicate = false) {
positionx = roughx;
}
platforms[ind] = new Platform(positionx,positiony,type);
}
var generatedplatforms = function(){
for (var i = 0; i < nrOfPlatforms; i++) {
generatePlatforms(i);
};
}();
you go big data, generate all possibilities, store each in an array, shuffle the array,
trim the first X items, this is your non heuristic algorithm.

for loop help, unknown syntax with javascript

say I wanted to use variables like
var userpos1 : int;
var userpos2 : int;
var userpos3 : int;
//in a for loop like
var i=1;
for (i=1;i<=3;i++)
{
userposi + 1
}
how would I place the i so that the for loop goes through all of my variables properly
var userpos1var : int;
var userpos2var : int;
var userpos3var : int;
//in a for loop like
var i=1;
for (i=1;i<=3;i++)
{
userposivar + 1
}
is there something I need to do to this i to make it work properly such as a "" or a [] around it?
Create an array of those vars and go over like this
for(i = 0; i < 3; i++)
{
func(arr[i]);
}
you should use an array of variables instead, but to do what you are wanting to do, you would write:
eval("userpos" + i + "var") + 1
eval can be unsafe to use, and does not peform well.
<script type="text/javascript">
var userpos1 = 1;
var userpos2 = 2;
var userpos3 = 3;
var i = 1;
for (i=1;i<=3;i++)
{
alert (eval("userpos" + i));
}
</script>
Why don't you use an array... ?
var userpos = new Array(3);
for (var i=0; i<userpos.length; i++) {}
{
userpos[i] = i;
}
This is much easier done by storing those values in a single array and iterating over the array.
someArray = new Array(1, 2, 3);
for (key in someArray)
alert(someArray[key] );
Instead of doing it this way, use an array of user positions:
//Create an array of 3 positions,
setting all to 0
var userPos=new Array(0, 0, 0);
//loop through each position - notice
starts at 0.
for (var i = 0; i < 2; i++)
{
userPos[i] += 1;
}
Eval() would do it, but we should not encourage the use of it. Instead, construct an anonymous function.
for ( i = 1; i <= 3; i++ ) {
alert(new Function('return userpos' + i + 'var;')()); // value of userpos1var
}
Update
JSFiddle example: http://jsfiddle.net/madr/AHBrd/
What you're looking for is:
var userpos = ['a','b','c'];
for(var i=0; i < userpos.length; i++) {
userpos[i]; // doing something with it.
}

Categories