I have an object with randomly generated data:
var obj = {
price: getRandomNumberRange(10, 200),
rooms: getRandomNumberRange(1, 5)
};
where
var getRandomNumberRange = function (min, max) {
return Math.floor(Math.random() * (max - min) + min);
};
I keep trying and failing to write a function, which will allow to create an array of 4 objects, so each objects' data will be regenerated at the time of creation. My function:
var createArr = function () {
var arr = [];
for (var i = 0; i < 5; i++) {
arr.push(obj);
}
return arr;
};
In other words I expect to get this kind of array:
var arr = [{price:40, rooms:2}, {price:23, rooms:4}, {price:99, rooms:2}, {price:191, rooms:3}];
But I keep getting this:
var arr = [{price:40, rooms:2}, {price:40, rooms:2}, {price:40, rooms:2}, {price:40, rooms:2}];
Will appreciate your help!
UPD. Thanks to everyone who suggested more complex way to solve my problem. As soon as I progress in JS I will recheck this thread again!
It looks like you reuse the object for pushing over and over and because of the same object, it pushes the same object reference with the latest values.
To overcome this, you need to create a new object for each loop and assign the random values with short hand properties.
// inside the loop
let price = getRandomNumberRange(10, 200),
rooms = getRandomNumberRange(1, 5);
array.push({ price, rooms }); // short hand properties
I'm pretty new (a few weeks in) to js and have a question about an incremental game I'm developing. My issue has to do with creating an array from an object I have and then fetching a property of the object, which is used in a compare statement and updated in my HTML.
I have the following object called UPGRADES:
var UPGRADES = {
newClothes: {
name: "New Clothes",
desc: "Give your bums a new look and some more motivation! \n Bum
production bonus: 100%",
moneyCost: 1000,
scienceCost: 10,
requiredScience: 10,
buildingAffected: BUILDINGS.bumBuilding,
upgVal: 2,
id: 'newClothes'
},
//{upgrade 2}
//{upgrade 3 etc.}
}
For one part of my code I need to go through each element of UPGRADES, return the nth object WITHIN "upgrades" (with newClothes as index 0), and then call (Nth index.scienceCost).
So far I've done the following:
var numBuildings = objectLength(BUILDINGS);
var numUpgrades = objectLength(UPGRADES);
function checkVisiblityOnUpgrades () {
var upgArray = [];
for (var a = 0; a < numUpgrades; a++) {
upgArray[a] = Object.keys(UPGRADES)[a].toString();
console.log(UPGRADES.upgArray[a]);
if (UPGRADES.upgArray[a].requiredScience <= resources.science) {
var idString = upgArray[a].id.toString();
getId(idString.concat("Button")).style.visibility = "visible";
getId(idString.concat("MoneyCostDisp")).innerHTML =
numFormat(upgArray[a].moneyCost);
getId(idString.concat("ScienceCostDisp")).innerHTML =
numFormat(upgArray[a].scienceCost);
}
}
}
I get this error along with it:
Uncaught TypeError: Cannot read property '0' of undefined
at checkVisiblityOnUpgrades (game.js:268)
at update (game.js:290)
268 is console.log(UPGRADES.upgArray[a]);
I was wondering how I would actually go about grabbing the values of the object I wanted. I'm creating an array in checkVisibilityOnUpgrades() so I can iterate through each upgrade with a for loop.
Another question I have is: If I was going to store 100+ instances of upgrades, would it be better to switch UPGRADES to an array rather than its own object? That way I could grab values a lot more easily.
You can drastically simplify your initial logic there with Object.entries:
Object.entries(UPGRADES).forEach(({ key, thisUpgradeObject }) => {
// `key` references the outer property, eg., 'newClothes'
// `thisUpgradeObject` references the inner object
});
So
Object.entries(upgArray).forEach(({ key, obj }) => {
const {
requiredScience,
id,
moneyCost,
scienceCost,
} = obj;
if (requiredScience < resources.science) return;
const idString = id.toString();
getId(idString.concat("Button")).style.visibility = "visible";
getId(idString.concat("MoneyCostDisp")).innerHTML = numFormat(moneyCost);
getId(idString.concat("ScienceCostDisp")).innerHTML = numFormat(scienceCost);
});
I see the problem here:
You create an array called upgArray, but then try to access UPGRADES.upgArray which is undefined. What you want to write there is likely UPGRADES[upgArray[a]].
function checkVisiblityOnUpgrades () {
var upgArray = Object.keys(UPGRADES);
for (var a = 0; a < numUpgrades; a++) {
if (UPGRADES[upgArray[a]].requiredScience <= resources.science) {
var idString = UPGRADES[upgArray[a]].id.toString();
getId(idString.concat("Button")).style.visibility = "visible";
getId(idString.concat("MoneyCostDisp")).innerHTML =
numFormat(UPGRADES[upgArray[a]].moneyCost);
getId(idString.concat("ScienceCostDisp")).innerHTML =
numFormat(UPGRADES[upgArray[a]].scienceCost);
}
}
}
I got to the point with my project where I decided to simplify some of the js functions where I am looking for a parent in a DOM tree, then drill down to the elements many many times in one function. instead I though I will make instances of a function which will keep some data so then I can refer and operate on objects in easy way. I got it working but as I was going along, I decided to extend functionality and add some extra functions like getElementsByClassNameThenTagName.
I loop through the arrays and if add matching elements to the array.
I have noticed (sadly only now) that I am creating an array with elements rather than HTML collection. As a results, I cannot refer to the objects in my findings by typing buttons['reset'].disabled = false;. I can access my reset button by buttons[3].disabled = false; but this would cause a lot of inconvenience.
I am therefore looking for a way to convert my array with object into a HTML collection.
Please see below my current function:
this.getElementsByClassNameThenTagName = function (elementClass, elementTag) {
if (parentNode == null) {
this.init();
}
var results = [];
var regexStr = elementClass;
var regex = new RegExp(regexStr);
var x = moduleNode.getElementsByClassName(elementClass);
// console.log(x);
var y;
for ( var i = 0; i < x.length; i++ ) {
// console.log(i);
y = x[i].getElementsByTagName(elementTag);
// console.log(y);
for (var k=0; k<y.length; k++){
// console.log(y[k]);
results.push(y[k]);
}
// console.log(results);
}
return results;
};
Any suggestions please?
Thanks.
this.getElementsByClassNameThenTagName = function (elementClass, elementTag) {
if (parentNode == null) {
this.init();
}
var results = {}; // thid should be an object (collection)
var x = moduleNode.querySelectorAll("." + elementClass + " " + elementTag);
x.forEach(function(y) {
var name = y.getAttribute("name"); // if you really sure that all the matched elements have names
results[name] = y;
});
return results;
};
Now you can use the results array like this:
var someElement = results['some name'];
NOTE: All the matched elements x should have a name attribute, and all the name attributes of the matched elements should be unique.
I am new to javascript,I am pretty confused with this uniform crossover stuff
What is uniform crossover ?
I have two array Like this
var ParentOne = ["j1","j2","j3","j4","j5"];
var ParentTwo = ["j3","j4","j2","j1","j4"];
How to do it
I've just wrote just rand Selection array
function uniqueRandomInts(upperLimit, amount) {
var possibleNumbers = _.range(upperLimit + 1);
var shuffled = _.shuffle(possibleNumbers);
return shuffled.slice(0, amount);
}
http://codepen.io/anon/pen/BpBOoB
Since you're pretty new to js, the linked codepen is written in ES6 syntax. In particular, it makes use of destructuring to help with array length reordering and array concatenation and uses of const versus var.
In particular, there is a use case not covered by the currently accepted answer. What happens if the parents are not of equal size?
By just iterating over one parent or another, if that parent is shorter than the other then data from the second parent is lost. If the parent is longer than the other one, then both extra cycles are wasted because there is no matching data on the short parent and errors are introduced into the child array with undefined for each missing array index.
In the code below, we first sort the parent arrays so the shortest is first. After creating the child, we then concatenate any remaining data from the longest parent to the end of the child array.
const parentOne = ['j1','j2','j3','j4','j5'];
const parentTwo = ['j3','j4','j2','j1','j4'];
const parentThree = ['j1','j2','j3','j4','j5', '#', '##', '###'];
const parentFour = ['j3','j4','j2','j1','j4'];
const parentFive = ['j1','j2','j3','j4','j5', '#', '##', '###'];
const parentSix = ['j3','j4','j2','j1','j4'];
// ensure parentOne is the shortest
const fn = (...parents) => {
// ensure shortest parent is first
[parents] = parents[1].length < parents[0].length ? [[parents[1], parents[0]]] : [[parents[0], parents[1]]];
// iterate over shortest parent
let child = parents[0].map((item, i) => parents[Math.round(Math.random())][i]);
// add the remaining elements from the longest array to the child
if (parents[1].length > parents[0].length) {
child = [...child, ...parents[1].slice(parents[0].length)];
}
return child;
}
console.log(fn(parentOne, parentTwo));
console.log(fn(parentThree, parentFour));
console.log(fn(parentFive, parentSix));
console.log('---');
You could rely on the fact, that both parents arrays have the same length and then just map the random items to a new array.
var p1 = ["j1", "j2", "j3", "j4", "j5"],
p2 = ["j3", "j4", "j2", "j1", "j4"],
output = p1.map(function(_, i) {
return [p1, p2][Math.round(Math.random())][i];
});
console.log(output);
ES6
var parent1 = ["j1", "j2", "j3", "j4", "j5"],
parent2 = ["j3", "j4", "j2", "j1", "j4"],
crossover = (p1, p2) => p1.map((_, i) => [p1, p2][Math.round(Math.random())][i]),
output = crossover(parent1, parent2);
console.log(output);
It looks like you want to create an output array with each element selected randomly from one of two input arrays. This is simple to do with a loop and basic random and rounding functions.
var ParentOne = ["j1","j2","j3","j4","j5"],
ParentTwo = ["j3","j4","j2","j1","j4"],
parents = [ParentOne, ParentTwo],
output = []; output.length = ParentOne.length;
for (var i = 0; i < output.length; i++) {
output[i] = parents[Math.round(Math.random())][i]
}
I wish to create an array called allEnemies, which contains "bugs" which belong to a Class "Enemy". I'm trying to do it in a for loop because later on the var "bug" will be modified. The problem is that the objects created "if I'm creating them" don't get into the array "allEnmies". Thank you in advance.
var allEnemies = [];
var random_speed = function() {
return Math.floor(Math.random() * (300 - 80)) + 80;
};
var random_y = function() {
var postions = [60, 143, 226];
return positions[Math.floor(Math.random() * 3)];
};
var create_enemies = function() {
var bugs = 4;
for (var i = 0; i < bugs; i++) {
var bug = new Enemy();
bug.speed = random_speed();
bug.y = random_y();
bug.x = 0;
allEnemies.push(bug);
}
};
Demo - http://jsfiddle.net/ubkusb6r/
Ok, so a few things:
1) Since you've declared the for loop using an anonymous function assigned to a variable you need to invoke the function via that variable create_enemies(). Without this, your code won't run.
2) You need to create an Ememy constructor (if you haven't done so yet).
3) You misspell positions at one place in your code...leading to an error.
Take a look at the JSFiddle and let me know if it answers your question (the fiddle includes console.log statements to track the array).