I am studying JavaScript and I believe I understand how these loops work. However, I got an exercise where I didn't understand which was the function of the counter for a new array being filled. This is the exercise:
var animals = ["goat", "cat", "crow"];
var products = ["milk", "cheese", "burger"];
var foodItems = [];
var k = 0;
for (var i = 0; i < animals.length; i++) {
for (var j = 0; j < products.length; j++) {
foodItems[k] = animals[i] + products[j];
k++;
}
}
console.log(foodItems);
The code above produces the array ["goatmilk", "goatcheese", "goatburger", "catmilk", "catcheese", "catburger", "crowmilk", "crowcheese", "crowburger"]. If I take out the [k] counter, it gives me an 1 element array [crowburger]; if I put a zero as the foodItems counter, it gives me [crowburger] as well, but bigger numbers produce undefined elements in the array before crowburger (i.e. foodItems[10] equals [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, "crowburger"]).
My question: what does the [k] counter do and why if it is replaced by numbers it produces undefined elements plus [crowburger?]
k is the index of the array. An array is a sorted list of elements and the standard access is to use an index to get the element at the given index. index is zero based, it starts from zero for the first element of the array.
If you take always the same index, the element at the given index is replaced by the new element.
The pattern
array[index] = value:
index++;
is like Array#push, which add the element at the end of the array without maintaining an index by hand.
array.push(value);
The k is the outer iterator. It's controlling the index of the global foodItems empty array, because if you declared it inside the scope of the loop, it wouldn't be accessible outside of the loop, and would vanish. So, commonly, you declare the outer array and iterator, and as you iterate through the loop, you're adding the values to the array and iterating over it.
Think of it like this:
var k = 0 // So we start on the first index of the foodItems array
var foodItems = []; // So it is declared empty at start
Here's what it's basically doing:
foodItems[k] (which is currently zero) is equal to animals[0] + products[0]... Then foodItems[1] is animals[0] + products[1] and so on.
The reason you can't use any number is because it doesn't have any indices when it starts, and you can't access the 5th (for example) element of an empty array.
The k counter is the index of the foodItems - In your case it cannot go higher than 9 which is 3x3.
So first time around you have k=0
foodItems[0] = "goat"+"milk"
second k++ (increment k by one)
foodItems[1] = "goat"+"cheese"
If you do not want the counter, just push to foodItems
i.e change foodItems[k] = animals[i] + products[j]; to foodItems.push(animals[i] + products[j]);
It will add the string to a new empty spot in foodItems on each push, making foodItems longer for each push
var animals = ["goat", "cat", "crow"];
var products = ["milk", "cheese", "burger"];
var foodItems = [];
for (var i = 0; i < animals.length; i++) {
for (var j = 0; j < products.length; j++) {
foodItems.push(animals[i] + products[j]);
}
}
console.log(foodItems);
Related
I have a question that is hard to describe. It's a tale of two arrays.
I have one array holding 50 objects. Per object, I want to call its specific property "IDnumber".
The second array is one that has 5 variables containing all of the mentioned 50 objects's "IDnumber" property, with each variable having a set of 10 IDnumbers: var1 is the IDnumbers of the first 10 objects, var2 is is the IDnumbers of the second set, and so on until the 50th object's ID number.
This is where it gets hard.
If I want to add in a new object in the first array, so that there'll be 51 objects, then I want to update the second array with a 6th variable, that contains all the remaining objects' IDnumbers (in this case just the 1). I want array2's length to be dependent on array1's length.
var arr1 = [], obj = {"IDNumber": "1"};
//this is an example array, all objects have the same ID here, but not in my real array
for (var i = 0; i < 51; i++) {
arr1.push(obj);
}
var var1 = [arr1[0]["IDNumber"], arr1[1]["IDNumber"], arr1[2]["IDNumber"], arr1[3]["IDNumber"], arr1[4]["IDNumber"], arr1[5]["IDNumber"], arr1[6]["IDNumber"], arr1[7]["IDNumber"], arr1[8]["IDNumber"], arr1[9]["IDNumber"]];
//the other remaining possible variables.
var arr2 = [var1, ...]; //No clue as how to take that on
How do I do that? How do I create an array that updates itself with newer possible variables like that? Each variable must have a max of 10 objects' IDnumbers.
Suppose array1 contains your array of objects. The other one is array2 containing an array of arrays, each sub array has length 10 like you stated
You can split array1 into groups of 10 and put in array2 like this
function slice10(arraysOfObject) {
var array2 = [];
var leftOver = arraysOfObject.length % 10;
var groupsOfTen = (arraysOfObject.length - leftOver)/10;
for (var i = 0; i < groupsOfTen; i++) {
array2.push([]);
for (var j = i*10; j < i*10 + 10; j++)
array2[i].push(arraysOfObject[j]["IDNumber"]);
}
//now take care of the leftover
if (leftOver > 0) {
array2.push([]);
for (var i = groupsOfTen*10; i < arraysOfObject.length; i++)
array2[array2.length-1].push(arraysOfObject[i]["IDNumber"]);
}
return array2;
}
You could create a function to deal with adding an object to the two different data structures, and use that function also for adding the first 50 objects:
function addObject(arr1, arr2, obj) {
if (arr1.length % 10 == 0) arr2.push([]);
arr1.push(obj);
arr2[arr2.length-1].push(obj.IDNumber);
}
var arr1 = [], arr2 = [];
for (var i = 0; i < 51; i++) {
addObject(arr1, arr2, {"IDNumber": i + 1000}); // some dummy ID value
}
console.log(arr2);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I want to push array A to B inside cycle and then and for every iteration of B i need to delete array A and create new one. I get all data before clearing the array, but after clearing I get array B with empty values
Code :
for (i = 0; i < XArray.length; i++) {
var pointsArray = [];
for (j = 0; j < XArray.length; j++) {
if (XArray[i] == XArray[j]) {
pointsArray.push([parseFloat(YArray[i]), parseFloat(ZArray[i])]);
}
}
dataSource.push({
name: i,
data: pointsArray
});
pointsArray.length = 0;
}
The last line
pointsArray.length = 0;
removes every element in the array you created in the first line. And since all objects are assigned by reference (and arrays are objects), the data property of the object will now point to an empty array. Here is a simplified example:
var a = [1, 2];
var b = a;
a.length = 0;
console.log(b); // [] -- an empty array
So, your current code has the same effect as
dataSource.push({
name: i,
data: []
});
Solution: Just remove the last line and it will work as expected.
I have an array that I am looping twice, one im looping from pointer 0 and up and the other im looping backwards.
But they produce different array layouts in console.log which i find strange .. this is what i have:
//array has a length of 3 [0,1,2]
var data = [],
data2 = [];
for(var i = 0; i < array.length-1; i++){
data[i] = {};
data[i].test = 'Hello';
}
for(var i = array.length - 1; i > 0; i--){
data2[i] = {};
data2[i].test = 'Hello';
}
console.log(data);
console.log(data2);
Now in my console log they come out different like this:
So why does the second one have a length of 3 but only 2 objects? And why does the second console.log have numbers in front of the objects unlike the first one ?
The length of an Array is simply the max(index) + 1.
When you create a "sparse" array, the intermediate indexes are still treated as existing.
console.log(JSON.stringify(data2));
// [null, {"test":"Hello"}, {"test":"Hello"}]
Even if the instance doesn't itself have them.
console.log('0' in data2);
// false
If you want a count of keys that were used, you could get the length of its Object.keys():
console.log(Object.keys(data2).length);
// 2
Possibly filtering to just indexes.
Object.indexes = function (target) {
return Object.keys(target).filter(function (key) {
return key === String(parseInt(key, 10));
});
};
console.log(Object.indexes(data2).length);
Note that these snippets expect an ES5-based engine or polyfills.
Your inner loop has this continuing condition:
i > 0
Which stops it before it gets to the data2[0] position.
And so, you're setting data2[2] and then data2[1]. data2[0] remains unset but it's still in the array (it's still the pointer position).
This is what you're looking for
for(var i = array.length - 2; i >= 0; i--){
data2[i] = {};
data2[i].test = 'Hello';
}
i have a java script array object and i want to delete items from a specific index in that object, i have a comma separated string of that indexes. problem is that when i delete it using splice array indexes got changed, and other indexes's object not got deleted.
var DeletedConditions="3, 5, 19, 50";
for (var k = 0; k < DeletedConditions.split(", ").length; k++) {
ConditionObject.splice(DeletedConditions.split(", ")[k], 1);
}
DeletedConditions string can be anything.
please help me out. how to get this done.
First of all, I suggest you officially turn the indexes into a formal array. Having a string as an index reference, you are prone to missing a split shall there be a case where the values are not separated by ,
Then the code:
var content = ['foo', 'bar', 'baz', 'bam', 'dom', 'zok'],
deleteIndexes = [5, 1, 3],//should delete zok, bar, bam
i;
//sort from least to greatest: [1, 3, 5]
deleteIndexes.sort(function(a, b) {
return a - b;
});
//we loop backwards (performance enhancement)
//now we loop from greatest to least
//we now splice from greatest to least
//to avoid altering the indexes of the content as we splice
for (i = deleteIndexes.length; i-- > 0;) {
content.splice(deleteIndexes[i],1);
}
console.log(content); //["foo", "baz", "dom"]
You can always decrement the k iterator after splicing inside the loop:
k--;
var DeletedConditions="3, 5, 19, 50";
var list = DeletedConditions.split(", ")
for (var k = 0; k < list.length; k++) {
// using splice here
list.splice(k,1);
k--;
}
console.log(list.join(', '))
Removing an item from the beginning of the array shuffles the later elements up and changes their indices, as you've observed. But if you go through the list of items to remove backwards then it will remove the later elements first so the indices will still be correct for the elements closer to the beginning of the array.
Also, please don't do the .split() operation on every loop iteration - the inefficiency might not make much difference on a string with four numbers in it, but it makes the code kind of messy and on principle it is just kind of yucky.
var DeletedConditions="3, 5, 19, 50",
delCondArr = DeletedConditions.split();
for (var k = delCondArr.length - 1; k >= 0; k--) {
ConditionObject.splice(delCondArr[k], 1);
}
If there's a possibility that the DeletedConditions strig might not be ordered just add a .sort() after you split it:
delCondArr = DeletedConditions.split().sort(function(a,b){return a-b;});
...in which case you don't need to loop backwards.
It might be easiest to copy the original array, omitting the deleted items in the process. Something like this would do the trick...
var DeletedConditions="3, 5, 19, 50";
DeletedConditions = DeletedConditions.split(', ');
var newConditionObject = [];
for(var k = 0; k < ConditionObject.length; ++k) {
if(DeletedConditions.indexOf(k) !== -1) { continue; }
newConditionObject.push(ConditionObject[k]);
}
// result is in `newConditionObject`
console.log(newConditionObject);
var fruits = new Array("apple", "banana", "grapes", "oranges","mosambi","aaa","bbb","ccc");
var DeletedConditions="1,3,4,5";
var indexArray = new Array;
indexArray = DeletedConditions.split(",");
for (var i = 0; i < indexArray.length; i++) {
fruits.splice(indexArray[i], 1);
}
http://jsfiddle.net/gfuKS/5/
var transitionInitial = {property: "none"};
var rules = ["color", "background-color"];
var transitions = [];
for ( var k = 0; k < rules.length; k++)
{
transitions[k] = transitionInitial;
transitions[k].property = rules[k];
alert(transitions[0].property);
}
Why at the second iteration transitions[0].property equals "background-color"?
Because you are storing a reference to transitionInitial, not a copy of it. transitionInitial points to an object in memory, and you are storing a reference to this object in transitions[k]. Regardless of the iteration you are at, you are always changing the same object.
It's because both values in your transitions array are pointing at the same object. During the execution of your code you produce one object that has three different references (transitionInitial, transistions[0], & transistions[1]).
During the first iteration of the loop, transistions[0] is set to reference the transitionInitial object. Then the property property of that object is set to the value "color". During the second iteration transitions[1] is set to reference the same object as transitionInitial and transitions[0]. You then reset the property's value to "background-color".
To solve this create different objects for each of your array indexes:
// Not needed anymore:
// var transitionInitial = {property: "none"};
var rules = ["color", "background-color"];
var transitions = [];
for ( var k = 0; k < rules.length; k++) {
transitions[k] = {};
transitions[k].property = rules[k];
alert(transitions[0].property);
}
Does it have anything with this to do maybe? for ( var k = 0; k < rules.length; k++)
Try changing the timer.