creating numbered objects from a constructor in javascript - javascript

I have a constructor that makes squares.
I would like my code to automatically create squares from this constructor using loops and name them square1, square2, square3 ect.
eg.
for (n=1; n < x; n++){
var square(n) = new Square();
}
Is this possible?
If so how and how do I refer to them in a loop - like square(n)?
I'm new to programming, oop and javascript so sorry if this is really ovb.
thanks in advance

That's what Arrays are for:
var squares = new Array();
for (var n = 1; n < x; n++) {
squares.push( new Square() );
}
Now you're able to access them with their zero-based index:
squares[0].someMethod(); // etc..
To iterate over all the squares in that array:
for (var i = 0; i < squares.length; i++) {
squares[i].someMethod();
}

That's a pretty nasty idea. Use an array for this purpose:
var squares = [];
for (var n = 1; n < x; n++) {
squares.push(new Square());
}
Anyway, if you really want to do it:
window['square' + n] = new Square();
This will create globals. There is no clean, eval-less way to create locals like that.

Related

Generate x number of objects

A desired x number of objects is to be created.
The system creates x number of objects.
for (i = 1; i <= x; i++) {
let obj = new Object()
}
I cannot seem to figure out how this can be done without the objects having the same name. I thought that naming them obj1 to objx using iteration to avoid conflicting names is a solution. However I do not know how to name objects and variables using the iteration number as part of its name.
You are looking for an array that holds all the different objects. In your loop, you can push the object to that array:
const objects = [];
for(let i = 1; i <= x; i++) {
let obj = {};
objects.push(obj);
}
Now you can get a certain object as:
objects[5] // the sixth object
Or you can go over all objects as:
for(const obj of objects)
console.log(obj);
As I understood you would like to be able dinamically create variables with different names.
It is possible but it is bad practice because we create global variables
for (i = 1; i <= x; i++){
window['obj' + i] = {i}; //iterate name
}
after that you can call obj1, obj2, ... and they are all global
I recommend to use local object or Map
const localObj = {};
for (i = 1; i <= x; i++){
localObj['obj' + i] = {i};
}
then you just write localObj.obj1, localObj.obj2 ...
const localMap = new Map();
for (i = 1; i <= x; i++){
localMap.set('obj'+i, i);
}
To get your data: localMap.get('obj1'), localMap.get('obj2') ...

Push same information to two arrays using a For Loop

Bit of a theoretical question, if I had a JavaScript application where I have multiple Players and for each player there will be 100 computer generated maths questions.
In single player mode it's easy, just generating the questions for the one player:
var player1Qs = [];
for (i = 0; i < maxQustions; i++) {
// Generate Question Object
var question = {};
...
// Add to Array
player1Qs.push(question);
}
That works with no issue. However, when I add a second player into the mix using the same sort of idea as above is where I get a bit puzzled. I'm tryinng to do it without using a multi-dimensional array becasue I'm trying to keep it as simple as possible, but it might be unavoidable.
So player 2 would look something similar to this:
var player1Qs = [];
var player2Qs = [];
for (i = 0; i < playerCount; i++) {
for (j = 0; j < maxQustions; j++) {
// Generate Question Object
var question = {};
...
// Add to Array
???
}
}
Would there be a way of me adding to those two arrays dynamically using a for loop? Or would I need a containing array of players and inside that an array for the questions?
Something like this should do the trick:
// Make sure all players exist.
var players = [];
for (var i = 0; i < playerCount; i++) {
players.push({ name: "Player " + i, questions: [] });
}
// Create questions
for (var i = 0; i < maxQuestions; i++) {
// Generate Question Object
var question = {};
// Do stuff with this question
// Assign the current question to all players.
for (var j = 0; j < playerCount; j++) {
players[j].questions.push(question);
}
}
I'm tryinng to do it without using a multi-dimensional array becasue I'm trying to keep it as simple as possible
I would argue that having a two-dimentional array is the simplest use-case, as you suggest in your question:
Or would I need a containing array of players and inside that an array
for the questions?
The answer is yes (at least if you want to keep it simple). The players array will keep all the players, and each player can then have 100 questions each.
var maxQustions = 100;
var players= []
var player1Qs = [];
var player2Qs = [];
players.push(player1Qs);
players.push(player2Qs);
for (i = 0; i < players.length; i++) {
for (j = 0; j < maxQustions; j++) {
var question = {};
players[i].push(question);
}
}
follow this approach, I assume you have dynamic players and its array:-
var data = {};
var player = [1,2]
var c = [1,2,3,4,5]
for(j=0;j<player.length;j++)
{
data['players'] = player;
data['questions'] = c
}
console.log(data)

Reassigning Lists in For Loops (JavaScript)

Apologies if this has been asked before - I couldn't find what I was looking for after a search, but I'm a beginner, so I might have missed something.
I am trying to implement Lloyd's algorithm in JavaScript (very crudely) to get some practice.
var k_means = function (array,number_clusters,max_loops) {
var initial_centers = underscore.sample(shelter_lat_lon,number_clusters);
var current_centers = initial_centers;
var current_associations = {};
for (p = 0; p < current_centers.length; p++) {
current_associations[current_centers[p]] = []
}
for (loops = 0; loops < max_loops; loops++) {
for (i = 0; i < array.length; i++) {
var current_loc = array[i]
temp_array = new Array();
for (j = 0; j < current_centers.length; j++) {
var distance_from_center = distance(current_centers[j],current_loc)
temp_array.push(distance_from_center)
}
var closest_center_lat_lon = current_centers[smallest_index(temp_array)]
current_associations[closest_center_lat_lon].push(current_loc)
}
new_clusters_temp = []
for (var key in current_associations) {
lat = []
lon = []
for (i = 0; i < current_associations[key].length; i++){
lat.push(current_associations[key][i][0])
lon.push(current_associations[key][i][1])
}
mean_lat = math_module.mean(lat)
mean_lon = math_module.mean(lon)
new_clusters_temp.push([mean_lat,mean_lon])
}
current_centers = new_clusters_temp;
}
}
Sorry for the ugly code. There are 2 module requirements - underscore and mathjs (mathjs is called math_module). Additionally, the function distance returns the Euclidean distance (I'm using 2 dimensional data), and smallest_index returns the index of the smallest element in an array.
The only problem I'm having is coming at the line
current_centers = new_clusters_temp;
Node returns the error "Cannot read property 'push' of undefined." After debugging a bit, it essentially thinks the array "current_centers" is empty. In Python, this is how I would reassign a list outside of a for loop. Is this different in JavaScript?
Cheers!
Alex

Google App Script arrays

I'm working on Google Script and I'm testing different ways to create two dimensions arrays.
I have created an array like this:
var codes = new Array(6);
for (var i = 0; i < 6; i++) {
codes[i] = new Array(4);
}
codes[0][0]="x";
codes[0][1]="x";
codes[0][2]="x";
codes[0][3]="x";
codes[1][0]="x";
codes[1][1]="x";
codes[1][2]="x";
codes[1][3]="x";
codes[2][0]="x";
codes[2][1]="x";
codes[2][2]="x";
codes[2][3]="x";
codes[3][0]="x";
codes[3][1]="x";
codes[3][2]="x";
codes[3][3]="x";
codes[4][0]="x";
codes[4][1]="x";
codes[4][2]="x";
codes[4][3]="x";
codes[5][0]="x";
codes[5][1]="x";
codes[5][2]="x";
codes[5][3]="x";
And it is working fine.
I read following links here, here and here.
But when I do it like this:
var codes = new Array(6);
for (var i = 0; i < 6; i++) {
codes[i] = new Array(4);
}
codes[0]=["x","x","x","x"];
codes[1]=["x","x","x","x"];
codes[2]=["x","x","x","x"];
codes[3]=["x","x","x","x"];
codes[4]=["x","x","x","x"];
codes[5]=["x","x","x","x"];
It didn't work, so I tried like this:
var codes = new Array([["x","x","x","x"],["x","x","x","x"],["x","x","x","x"],["x","x","x","x"],["x","x","x","x"],["x","x","x","x"]]);
it didn't work either.
When the code don't work, I get no error, just no display of the values.
What am I doing wrong? It looks to be the same code and the two not working ways are recommended in many documentations.
W3schools says that there is no need to use new Array().
For simplicity, readability and execution speed, use literal method ex:
var animals = ["cat", "rabbit"];
Reason why your code was not working is that you're equaling codes inside the loop and after end of loop scope 'codes' is getting only the last set array. Instead you should push those arrays to codes.
var codes = [];
for (var i = 0; i < 6; i++) {
codes.push([i]);
}
console.log(codes)
codes[0]=["x","x","x","x"];
codes[1]=["x","x","x","x"];
codes[2]=["x","x","x","x"];
codes[3]=["x","x","x","x"];
codes[4]=["x","x","x","x"];
codes[5]=["x","x","x","x"];
Better yet, two for loops to create the double array:
var codes = [], // Initiate as array, in Javascript this is actually fastre than using new (I don't know any cases you should use new)
rows = 6,
columns = 6;
for (var i = 0; i < rows; i++){
codes.push([]); // Initiate
for (var j = 0; j < columns; j++){
codes[i][j] = 'x';
}
}
Other idea, pre-initiate an array with the correct columns then copy:
var arrTemp = [],
codes = [],
rows = 6,
columns = 6;
for (var j = 0; j < columns; j++)
arrTemp[i] = 'x';
for (var i = 0; i < rows; i++)
codes.push( arrTemp.slice(0) ); // If you just push the array without slice it will make a reference to it, not copy
Other way to pre-initiate the array with 'x's:
arrTemp = Array.apply(null, Array(columns)).map(function () {return 'x'});

What is the best way to do loops in JavaScript

I have stumbled into several methods of looping in JavaScript, what I like the most is:
for(var i = 0; i < a.length; i++){
var element = a[i];
}
But as tested here (http://www.robertnyman.com/2008/04/11/javascript-loop-performance/), it should probably be written so that the length is only calculated once.
In jQuery there is a .each that you can stick a function. I like this a little better, because I don't have to type the array twice, like in the above solution.
If JavaScript supported macros it would be a piece of cake to roll your own, but sadly it does not.
So what do you guys use?
I've started using iterators where relevant. Performance is reasonable, however more importantly it allows you to encapsulate the looping logic:
function createIterator(x) {
var i = 0;
return function(){
return x[i++];
};
}
Then to use:
var iterator=createIterator(['a','b','c','d','e','f','g']);
iterator();
returns "a";
iterator();
returns "b";
and so on.
To iterate the whole list and display each item:
var current;
while(current=iterator())
{
console.log(current);
}
Be aware that the above is only acceptable for iterating a list that contains "non-falsy" values. If this array contained any of:
0
false
""
null
NaN
the previous loop would stop at that item, not always what you want/expect.
To avoid this use:
var current;
while((current=iterator())!==undefined)
{
console.log(current);
}
Small improvement to the original, to only calculate the array size once:
for(var i = 0, len = a.length; i < len; i++){ var element = a[i]; }
Also, I see a lot of for..in loops. Though keep in mind that it's not technically kosher, and will cause problems with Prototype specifically:
for (i in a) { var element = a[i]; }
Just store the length in a variable first.
var len = a.length;
for (var i = 0; i < len; i++) {
var element = a[i];
}
I know I'm late to the party, but I use reverse loops for loops that don't depend on the order.
Very similar to #Mr. Muskrat's - but simplifying the test:
var i = a.length, element = null;
while (i--) {
element = a[i];
}
You could just always use a while loop, and compute the array limit before hand.
Var max = a.length-1;
var i = 0;
while(i <= max)
{
var element = a[i];
i++;
}
If you have many elements in the array and speed is an issue then you want to use a while loop that iterates from highest to lowest.
var i = a.length;
while( --i >= 0 ) {
var element = a[i];
// do stuff with element
}
I don't use it myself, but one of my colleagues uses this style:
var myArray = [1,2,3,4];
for (var i = 0, item; item = myArray[i]; ++i) {
alert(item);
}
like Ash's answer, this will hit issues if you've got "falsey" values in your array. To avoid that problem change it to (item = myArray[i]) != undefined
I don't see what the problem with using a standard for(;;) loop is.
A little test
var x;
var a = [];
// filling array
var t0 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
a[i] = Math.floor( Math.random()*100000 );
}
// normal loop
var t1 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
x = a[i];
}
// using length
var t2 = new Date().getTime();
for( var i = 0; i < a.length; i++ ) {
x = a[i];
}
// storing length (pollution - we now have a global l as well as an i )
var t3 = new Date().getTime();
for( var i = 0, l = a.length; i < l; i++ ) {
x = a[i];
}
// for in
var t4 = new Date().getTime();
for( var i in a ) {
x = a[i];
}
// checked for in
var t5 = new Date().getTime();
for( var i in a ) {
if (a.hasOwnProperty(i)) {
x = a[i];
}
}
var t6 = new Date().getTime();
var msg = 'filling array: '+(t1-t0)+'ms\n'+
'normal loop: '+(t2-t1)+'ms\n'+
'using length: '+(t3-t2)+'ms\n'+
'storing length: '+(t4-t3)+'ms\n'+
'for in: '+(t5-t4)+'ms\n'+
'checked for in: '+(t6-t5)+'ms';
console.log( msg );
results in:
filling array: 227ms
normal loop: 21ms
using length: 26ms
storing length: 24ms
for in: 154ms
checked for in: 176ms
So:- for in's take the longest, using the length property (which is a property and doesn't need to be calculated) is nearly as fast as storing it first - which is only a whisker slower than using an integer.
AND a for() is the usual way to loop over an array, which everyone expects and understands.
All of them add a variable to the scope they run in - i - which is a common name for this use and so shouldn't be used for other things. Storing the length first adds another var - l - to the scope, which is unnecesary
So, first you identify the perfect javascript loop, I believe it should look like this:
ary.each(function() {$arguments[0]).remove();})
This may require the prototype.js library.
Next, you get disgustet with the arguments[0] part and have the code be produced automatically from your server framework. This works only if the ladder is Seaside.
Now, you have the above generated by:
ary do: [:each | each element remove].
This comes complete with syntax completion and translates exactly to the above javascript. And it will make people's head spin that haven't used seasides prototype integration before, as they read your code. It sure makes you feel cool, too. Not to mention the gain in geekiness you can get here. The girls love it!

Categories

Resources