Consider:
var main = []
Now I want to generate many (289 to be exact) Arrays to be elements in the main one. Each of these arrays will have be like:
var subobject = {x:"A", y:"B", terrain:"C", note:"D"}
Generating the values are no problem, and I can easily put those values in a already defined subobject = {} and push(), but I can't figure out how to iterate a script each time which creates a new object and then push() into var main.
The naming of the subobject is unimportant, I'm looking for solution inwhich I can pull specific information such as:
main[0].x // get x value of the subarray in 0 location in main
main[5].note// get note value of the subarray in 5 location in main
(would it make a difference if every array had the same name? since I would never access subobject directly (after being pushed into main), but through main[X].YYY or would it have to be via main[X].subarray[Y] ?)
for (var i = 0; i < 289; i++) {
main.push({x: getRandomX(), y: getRandomY(), terrain: getTerrain(), note: ""});
}
as long as you create new objects {} before you push them to the array it is ok.
it doesn't matter if you assign the new object to the same variable (ie subobject)
you access them later like this:
main[0].x // get the value of x of the first element
[x:"A", y:"B", terrain:"C", note:"D"] isn't valid javascript, I think you want an object here:
{x:"A", y:"B", terrain:"C", note:"D"}
And to push each generated value, you can use a for loop
for (var i = 0; i < 9; i++) {
//do something, for example, generate a value
}
Arrays are only numerically indexed.
If you want named keys you have to use objects.
Here's the wrong way to do it.
var main = [],
subobject = {x:"A", y:"B", terrain:"C", note:"D"};
for(var i=0; i<289; i++){
subobject["x"] = Math.random();
subobject["terrain"] = Math.random();
//continue adding values using keys
main.push(subobject);
}
The thing is if you just use the same object your going to access that object every time you iterate it, and you'll replace it's value.
So you should do it like this.
var main = [],
subobject = {};
for(var i=0; i<289; i++){
subobject = {};//new object to make for uniquness
subobject["x"] = Math.random();
subobject["terrain"] = Math.random();
//continue adding values using keys
main.push(subobject);
}
You access members like this.
main[0].x;//value of x at index 0
//next index
main[1].terrain;//value of terrain at index 1
Collisions will only happen if you set the same index twice.
main[2].x = "value";
main[2].x = "replace value by accident";
Unless you want to change the value for some reason.
A different index will always give you a different object if you set a different one each time.
Related
I am using this script to remove JSON objects from an array, which both appear within the array and another JSON object:
var stageChildren = stage.sprites;
for (var i = 0; i < stageChildren.length; i++) {
for (var x in mainMenu) {
if (mainMenu[x] === stageChildren[i]) {
console.log(x);
}
}
}
To make this more understandable, lets say I had two objects called: object1 & object2.
Inside object1, there may be the same JSON object which also appears within object2. If that's the case, the object is removed from object1.
While this script works, I think it might have a huge impact on performance. Why? Well, there's about 50 separate objects within stageChildren, and 10 inside mainMenu. The script loops through the first object inside stageChildren, checks if that object is also inside mainMenu (by performing a for loop again), and moves onto the next 49 objects.
Is there a more optimized way of doing this?
var index = 0;
var stageChildren = stage.sprites;
for (var x in mainMenu) {
if (stageChildren.includes(mainMenu[x])) {
const result = stageChildren.includes(mainMenu[x])
var index = stageChildren.indexOf(result);
stageChildren.splice(index, 1);
}
}
I am trying to sort a 2D array of custom objects, inside each inner array, based on one of the properties. This sub-arrays each represent one class, the outer array all the classes in the school. My strategy is as such:
Make a copy of the arry to provide a framework with the correct number of subarrays and indeces
Pass a copy of the sub-array to variable
Iterate over that array (the class) and pull out the last name from the object (which holds a number of other pieces of data on the child) and place it in an array that will be the index
Sort the index
Iterate over the class array, find the position of the last name in the index array, and insert the object into that index into the copied 'school'.
But this is not working. In some instances, one or two objects end up in the wrong place, in other instances it completely out of order. I have tried inspecting my index and comparing it with the 2D array, but the index is correct and I can't figure out why its not working. Here is the code:
var studentsInClass = // I have a function here that returns the 2D array of classes containing custom objects
var sortedStudentsInClass = studentsInClass;
var singleClassHolder = [];
var studentIndex = [];
// each iteration is for a single class
for(var i = 0; i < studentsInClass.length; i ++){
studentIndex = [];
singleClassHolder = studentsInClass[i];
// populate the student reference index
for(var j = 0; j < singleClassHolder.length; j++){
studentIndex.push(singleClassHolder[j].ID);
}
studentIndex.sort();
// iterate through students of single class, placing them in alphabetical order
for(var k = 0; k < singleClassHolder.length; k++){
sortedStudentsInClass[i][studentIndex.indexOf(singleClassHolder[k].ID)] = singleClassHolder[k];
}
}
return sortedStudentsInClass;
}
In case the object is important:
function Child(last, first, id, classroom, serviceDays, eligibility){
this.lastName = last;
this.firstName = first;
this.ID = id;
this.class = classroom;
this.maxServiceDays = serviceDays;
this.eligibility = eligibility;
}
And just a side note, it may seem extraneous having created the new singleClassHolder variable. After I noticed I did that, I removed it and just iterated through the 2D array, but that resulted in even more elements out of place.
Make a copy of the arry
var sortedStudentsInClass = studentsInClass;
This won't make a copy. It only makes one variable reference the other in memory. They both refer to the same array in memory. See related answer here.
The easiest way to fix the code is by declaring sortedStudentsInClass as a new array.
var studentsInClass = get2DArrayOfClasses();
var sortedStudentsInClass = [];
/*...*/
for(var k = 0; k < singleClassHolder.length; k++){
sortedStudentsInClass[i] = sortedStudentsInClass[i] || [];//declare inner array, if not present
sortedStudentsInClass[i][studentIndex.indexOf(singleClassHolder[k].ID)] = singleClassHolder[k];
}
I'm given the task to deduce and explain the lines of codes of a counter program. Below are the codes to the program which is working perfectly. I have included my explanations as comments in the code but it seems my explanation for the last 4 lines of codes (starting from ... "if(counter[index][entry] === undefined){...}") doesn't really explain it.
Can anyone please read the codes and give me a better explanation to them especially why we equate "counter[index][entry] = 1".
<script>
//an array containing a list of objects with sub arrays that has to be
//counted "separately"
var arr = [
{"gateways":["ccu1"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":
["ip_cam","ip_other"]},
{"gateways":["v3"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":
["ip_cam"]},
{"gateways":["v2","v3","v4","ccu2"],"manufacturer":
["homematic","intertechno"],"ir":["ir_yes"],"ip":
["ip_cam","ip_other"]},
{"gateways":["v2","ccu1","ccu2"],"manufacturer":["homematic"],"ir":
["ir_yes"],"ip":["ip_cam","ip_other"]},
{"gateways":["gw_none"],"manufacturer":["homematic"],"ir":
["ir_no"],"ip":["ip_cam"]},
{"gateways":["v3","ccu2"],"manufacturer":
["homematic","fs20","intertechno","elro","Eltako Enocean"],"ir":
["ir_yes"],"ip":["ip_cam","ip_other"]},
{"gateways":["v3","v4"],"manufacturer":["homematic"],"ir":
["ir_no"],"ip":["ip_other"]},
{"gateways":["v3","v4"],"manufacturer":["homematic"],"ir":
["ir_no"],"ip":["ip_other"]},
{"gateways":["v2"],"manufacturer":["intertechno"],"ir":["ir_yes"],"ip":
["ip_other"]},
{"gateways":["v4"],"manufacturer":["homematic","intertechno"],"ir":
["ir_yes"],"ip":["ip_cam","ip_other"]}
];
//console.log(arr.length);
//first we create an empty array "counter" to contain the separately
//counted objects
var counter = [];
//we then use "for loop" to loop through the "arr" array to access the
//first index
for(var i=0; i<arr.length; i++) {
//console.log(arr[i]);
// we create a variable "obj" to store the first index object of
//the "arr" array and because it is a loop,
//it will loop till the last object
var obj = arr[i];
//so if we console log "obj", it will display the entire indexes in
//the "arr" array including keys
//console.log(obj);
//we then use "for in" loop to access all the keys in the variable
// "obj" because we wanna count the number
//of all respective sub arrays
for(var index in obj) {
//so if we console log "index", it will display the entire keys in
// the "obj" variable; ie:
//in every object, it will run 4X to access all the keys
//console.log(index);
//in the next two lines of codes, we have to check if the keys in
// our counter array already exist because
//this is where we gonna put or store our counted respective sub
//arrays. if it doesn't exit, we create it.
if(counter[index] === undefined) {
counter[index] = [];
}
//so if we console log "counter[index]", it will show empty
//arrays which is gonna contain the respective key counts
//console.log(counter[index]);
//next we save the respective arrays to be counted without the
// keys in a variable "arr2".
var arr2 = obj[index];
//console.log(arr2);
//now we wanna loop through the "arr2" array because it
//contains the entries (in arrays) we wanna count
///starting from the first index to the last
for(var j = 0; j < arr2.length; j++) {
//we then store the single entries in a variable called "entry"
//(not with keys or in an array)
var entry = arr2[j];
//console.log(entry);
//in the next two lines of codes, we have to check if the keys
//in our counter array exist because this is where
//we would count "entry"
if(counter[index][entry] === undefined) {
counter[index][entry] = 1;
//console.log(counter[index][entry]);
} else {
counter[index][entry]++;
}
}
}
}
console.log(counter);
</script>
If counter[index][entry] is undefined, it means that we haven't began counting it yet. So we need to start counting it. So we count once, which sets the counter to 1.
If counter[index][entry] does exist (the else clause), it means that there's already a number in counter[index][entry] (because that's what we initialize it to if it doesn't), so just increment the number by one.
Another, perhaps clearer way of writing this would be:
if (counter[index][entry] === undefined) {
counter[index][entry] = 0; // If it doesn't exist, initialize counter to 0.
}
counter[index][entry]++; // Here the counter is a number for sure, increment once.
Basically it's trying to count how many each specific property exists. Eg, how many occurences of gateway v2, how many times ip_other exists etc.
The part with 'if(counter[index] === undefined)' is weird. Counter is an array. And index is the key from an object (namely gateway, manufacturer, ip and ir) So basically it's trying to set keys on an array. Although this is valid javascript, counter should be an object instead of an array to be 'more logical'. Hence the code looks a bit confusing.
Anyways, the rest works like madara posted.
If i declare this
var data = [];
data [300] = 1;
data [600] = 1;
data [783] = 1;
I have an array of length 784 but with only 3 defined items within it.
Since splice(300,1) would delete the item and the index but would also shift every consecutive position, how can i delete the object in the index 300 from the array without altering the order of the array so when i use
for(var x in data)
it can correctly iterate only 2 times, on the indexes 600 and 783?
i tried using data[300] = undefined but the index 300 was still iterated over.
You could use delete:
delete data[300];
This sets the value of the index to be undefined, but doesn't modify the element index itself.
See more about the delete operator here.
dsg's answer will certainly work if you're going to use an array. But, if your data is going to be as sparse as it is, I wonder if a plain Javascript object might be a better choice for such sparse data where you never want the index/key to change. Arrays are optimized for consecutive sequences of data starting with an index of 0 and for iterating over a sequence of values. And, they keep track of a .length property of the highest index used minus one.
But, since you aren't really doing any of that and given the way you are storing data, you aren't able to use any of the useful features of an array. So, you could do this instead with a plain Javascript object:
var data = {};
data [300] = 1;
data [600] = 1;
data [783] = 1;
delete data[300];
This would create an object with three properties and then would delete one of those properties.
You can then iterate over the properties on an object like this:
for (var prop in data) {
console.log(data[prop]);
}
A couple things to remember: 1) The property names are always strings so your numbers would show us as "600" in the prop variable in the above iteration. 2) Iterating with the for/in technique does not guarantee any order of the properties iterated. They could come in any order since properties on an object have no innate order.
You can delete that element from the array:
delete data[300];
The full example:
var data = [];
data [300] = 1;
data [600] = 1;
data [783] = 1;
delete data[300];
var result = "";
for (var x in data) {
result += "<div>" + x + "</div>";
}
document.getElementById("output").innerHTML = result;
<div id="output" />
I have an array defined as:
var subjectCache = [];
I then have some code to build it up, which is working ok.
However, if I try to reference the array by an index, e.g.:
var x = subjectCache[0];
or
var x = subjectCache[1];
I get undefined.
Also subjectCache.length is always 0 (zero).
if I try to reference it by its key, e.g.:
var x = subjectCache['12345'];
it works.
Is this normal? Shouldn't I be able to reference it by its index whatever?
I'm using Internet Explorer, if it makes a difference (and it probably does :( )
[Edit]
this is the code I'm using to build the array, although I really don't think it is to blame.
It's a callback from a webservice call. This is working fine and the array is being populated.
var subjectCache = [];
var subjectCacheCount = 0;
function refreshSubjectsCallback(data) {
// update subjects
// loop through retrieved subjects and add to cache
for( i=0; i < data.length; i++ )
{
var subject = data[i];
var subjectid = subject.SubjectId;
subjectCache[subjectid] = subject;
subjectCacheCount += 1;
}
}
[/Edit]
You're probably assigning keys manually instead of using subjectCache.push() to add new elements to the array:
var array = [];
array['foo'] = 'bar';
console.log(array.length); // 0
The length attribute isn't going to reflect those changes the way you'd expect:
> var a = [];
undefined
> a[100] = 2; // The previous `100` entries evaluate to `undefined`
2
> a.length;
101
Instead, use an object:
var object = {};
object['foo'] = 'bar';
for (var key in object) {
var value = object[key];
console.log(value);
}
From your symptoms, it sounds like you are trying to treat the array as an associative array.
In Javascript, arrays work like this:
var a = [];
a[1] = 10;
alert(a.length);
Objects work like this:
var o = {};
o.myProp = true;
o["myOtherProp"] = false;
Arrays only work with numeric keys not strings. Strings assign properties to the object, and aren't counted as part of length nor it's numeric indices.
When building the array, make sure you are assigning to a numeric position within the array.
No, it will not work, because you haven't created arrays but objects.
you will have to access it by its key.
var x = subjectCache['12345'];
If this works and subjectCache.length doesn't, I think you are making an object not an array. You are confused.
Somewhere along the road you lost the array, and the variable subjectCache points to a different kind of object.
If it was an array, it can't have the length zero and contain an item that is reachable using subjectCache['12345']. When you access an item in an array it doesn't make any difference if you use a numeric index or a string representing a number.