Recursive function inside for loop not working as expected [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I was trying to print first array element using recursive function but output is not as expected.
var modelArray = [1,2,3];
var refurbArray = [a,b];
for (var z = 0; z < modelArray.length; z++) {
for (var y = 0; y < refurbArray.length; y++) {
var check = modelArray[z];
var recursive(refurbArray[y], function() {
consol.log(check);
});
}
}
Expected output:
1
1
2
2
3
3
Obtained output:
3
3
3
3
3
3

The problem you are having is that recursive have deferred the call to your call back function (likely due to some async functionality inside the recursive), and the value of check has changed when the callback function is finally executed.
You need to bind the check in a closure, for which there are several options and coding style on how to do, but example like
for (var z = 0; z < modelArray.length; z++) {
for (var y = 0; y < refurbArray.length; y++) {
(function() {
var check = modelArray[z];
recursive(refurbArray[y], function() {
consol.log(check);
});
})();
}
}

Try with something like:
var modelArray = [1,2,3];
var refurbArray = ['a','b'];
function recursive(val, cb){
cb();
}
for (var z = 0; z < modelArray.length; z++) {
for (var y = 0; y < refurbArray.length; y++) {
var check = modelArray[z];
recursive(refurbArray[y], function() {
console.log(check);
});
}
}
You print the check variable in the refurbCallback and that remains set to the last value of var check = modelArray[z];

Related

Arrays inside an array Javascript [duplicate]

This question already has answers here:
How to check if object property exists with a variable holding the property name?
(11 answers)
Closed 5 years ago.
I want to make an array so that it contains some identity name and for each of those names there is another array associated. My approach is like,
for (var i = 0; i < 10; i++) {
for (var x = 0; x < 5; x++) {
var data = someServiceCall(i, x);
var identityName = i + '-' + x;
myArray[identityName] = data;
}
}
after executing this i get something like,
[1-1: Array(8), 1-2: Array(10), 1-3: Array(10), 1-4: Array(10),.. etc]
the next time I call this function I need to check whether 1-1 exists and if yes I need to get the list related to 1-1. How can I do this..? if 1-1 is not in the myArray I will call some other function.
To check if the element having the 1-1 key exists just do:
if("1-1" in myArray)
Then to access the array associated with 1-1 use:
myArray["1-1"]
Try this. It inserts an object containing the identity name and data in each array element.
var myArray = [];
for (var i = 0; i < 10; i++) {
for (var x = 0; x < 5; x++) {
var data = someServiceCall(i, x);
var identityName = i + '-' + x;
var objectInArr = {
'identityName': identityName,
'data' : data
};
myArray.push(objectInArr);
};
};
try like this
myArray["1-1"] != undefined
Check if key exists in your array or not and act accordingly. Following is a working code snippet
var myArray = [];
for (var i = 0; i < 10; i++) {
for (var x = 0; x < 5; x++) {
var identityName = i + '-' + x;
myArray[identityName] = [1, 2];
}
}
var key = "0-0";
if(myArray[key])
console.log(myArray[key]);
you can check your array lenght and if the array is empty you will know that you need to call another action as you say. something like below might work for you
if (myArray.length === 0) {
//Call another function}
else {
//Somthing else}

Output abnormal .. WHY? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I have many days that I can not run this script!
var b = [9,8,7,6,5,4,3,2,1];
var a = (function(){
var W = [];
for(var k in b){
W[W.length] = {
index : k,
fx : function(){
console.log(k);
}
}
}
return W;
})();
console.log(a);
for(var j = 0; a[j]; j++)a[j].fx();
Because it does not produce as OUTPUT numerical sequence 987654321?
Each function fx that you create references the variable var k. They don't save the current value of k, only a reference to k. This means that when you run the functions, after the for loop has finished, the value of k is now 8, and they all print that.
Once way to avoid this, and give each function its own variable/value, is to change var k to let k (available since ECMAScript 6). See let at MDN.
var b = [9,8,7,6,5,4,3,2,1];
var a = (function(){
var W = [];
for (let k in b) {
W[W.length] = {
index : k,
fx : function(){
console.log(k);
}
}
}
return W;
})();
for(var j = 0; a[j]; j++)
a[j].fx();

How to copy parts of an 2d array? [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
Closed 6 years ago.
I'm using JavaScript in google app script and I'm super confused why there is no simple way to copy stuff by value. I just want a simple way to copy a part of my matrix values2 into the new matrix matrix1. Why is that not possible?
var temp = [];
for (var t = 0; t<9;t++) {temp[t]= 0;}; //[0,0,0,0,0,0,0,0,0]
var matrix1 = [];
for (var x = 0; x<20;x++) {matrix1[x]=temp;};
for (var x = 0; x < 20; x++) {
for (var y = 0; y < 9 ; y++) {
matrix1[x][y] = values2[x+1][y+1];
}};
The code above fills the matrix with identical (last) lines.
Passing array as reference is common among programming languages. In this case, you don't even need temp:
var matrix1 = [];
for (var x = 0; x < 20; x++) {
matrix1[x] = [];
for (var y = 0; y < 9; y++) {
matrix1[x][y] = values2[x + 1][y + 1];
}
};

Stop passing by reference in closures [duplicate]

This question already has answers here:
How do JavaScript closures work?
(86 answers)
Closed 7 years ago.
I have code that looks like this:
var a = [];
for(var i = 0; i < 10; i++) {
a[i] = function() {
console.log(i);
}
}
Unfortunately, it seems that i is being passed by reference, so all the functions in a output 10. How do I make it so that each function outputs the value that i had when it was created? I.e. a[0]() gives 0, a[1]() gives 1, etc.
EDIT: to clarify, I do not want a to store the values 0-9. I want a to store functions that return the values 0-9.
You need to invoke a function (to create a closure that captures your value) which returns a function (the one you want to end up with). Something like this:
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = (function(value) {
return function() {
console.log(value);
}
})(i);
}
var a = [];
for(var i = 0; i < 10; i++) {
a[i] = (function(j) {
return function () {
console.log(j);
}
})(i);
}
A better performing version -
function makeFunction(i) {
return function () {
console.log(i);
}
}
var a = [];
for(var i = 0; i < 10; i++) {
a[i] = makeFunction(i);
}
JSFiddle Demo.

Why (many objects in objects) faster than (many elements in one object)?

I have ~16.000 items (one item is an array, has 6 values). All items have 5 "attributes", they're numbers. I need to store them, and when I know the attributes, return the item, as fast as possible. I tried 2 kind of methods:
Objects in objects. If a = attribute1, b = attribute2 ... to e, then I can get the item the user's looking for by data1[a][b][c][d][e]. The full data stored in this format: http://jpst.it/z12-
One object, but it has 16k arrays, the object's properties are the given item's attributes. Then myItem = data2[""+a+b+c+d+e]. http://jpst.it/z13p
I ran some tests to see which method is the faster:
var test,
a = 30175,
b = 5,
c = 1,
d = 1,
e = 60,
abcde = 301755360;
console.time("test1");
for (var i = 0; i < 9999999; i++)
test = data1[a][b][c][d][e];
console.timeEnd("test1");
console.time("test2");
for (var i = 0; i < 9999999; i++)
test = data2[abcde];
console.timeEnd("test2");
Results on my PC:
test1 test2
Firefox: 1482.00ms 1341.00ms
Chrome: 665.00ms 424.00ms
Explorer: 12555.17ms 4945,50ms
The second method is always faster. But why? I ran another test to know how many times the JS have to check if the given object's key equals to the needed key:
var x = 0;
function fn(obj, myKey) {
for (var key in obj) {
x++;
if (key == myKey)
return obj[key];
}
}
Method 1: fn(fn(fn(fn(fn(data1, a), b), c), d), e); => x is 352.
Method 2: fn(data2, abcde); => x is 3154.
However, method 2 isn't 10x slower, it's even faster.
This might give you an idea of what's going on. 2nd getter is called 9 times, first getter is called 45 times. Each time it first has to access 30186, then 6, then ... 5 calls for each iteration to get the value.
var x = 0;
var y = 0;
var data1 = {"30186":{"6":{"1":{"1":{"0":[4,1430745862,"3 - 5 ref","4 ref","4 ref",1]}}}}};
var data2 = {"3018663":[4,1430745862,"3 - 5 ref","4 ref","4 ref",1]};
Object.prototype.get = function(i) { x++; console.log(i); return this[i]; }
Object.prototype.get2 = function(i) { y++; return this[i]; }
for (var i = 0; i < 9; i++)
test = data1.get(30186).get(6).get(1).get(1).get(0);
for (var i = 0; i < 9; i++)
test = data2.get2(3018663);
console.log(x, y);

Categories

Resources