How to break for loop from function? - javascript

I have an update function which call a process function. Sometimes I need to break the for loop, but to do that I need to communicate from the process function to the loop running in update().
I'm passing a false to detect the break intention in process().
Is this a good way of interrupting the for loop in update()?
var system = {
update: function() {
for (var i = 0 ; i < 10 ; i++) {
var r = this.process(i);
if (r == false) break;
}
},
process: function(i) {
console.log('test ' + i);
if (i == 4) return false;
}
}
system.update();

Related

Javascript: Waiting for one (or multiple) condition in For Loop

I want to check a condition for k times for a value to be true, inside a For loop, each time I want to wait 2 seconds, after that I want to go next iteration of the for a loop. For example, I tried something like below -
var k = 0;
for (let i = 0; i < B.length; i++) {
setTimeout(function F_stTimer() {
if (B[i].innerText === "S") {
var A = "True"; //just for example
if (A === true && k == 0) {
// Do something
k = k + 1;
i = i - 1; // so , I can check the ith element again once start the loop again
} //if
else if (A === true && k > 0 && k < 5) { //checking 5 times for A to be false
k = k + 1;
}, i * 2000);
i = i - 1;
} //if
else if (A === true && k == 5) {
k = 0;
} //if
} // if
}, 5000);
} // i loop
But the above type of code is not working because I do not change when it is inside setTimeout.
Anyway, can anyone help me with the problem I have?
One does not need to follow the way I mentioned above, what I want to do is-
check a condition for k times for a value to be true, inside a For loop, each time I want wait t seconds (duration of each delay/interval of delay), after that, I want to go next iteration of the for a loop.
Plz comment for further clarification.
You could take an interval and check a counter.
var counter = 0,
interval = setInterval(function () {
counter++;
if (counter === 5) {
counter = 0;
console.log('five');
} else {
console.log('not five');
}
}, 1000);
You could write a function that takes two arguments:
howManyTimes - number of times you want to iterate
howOften - in what intervals you want to do the check (in milliseconds)
function checkInIntervals(howManyTimes, howOften) {
var counter = 0;
var interval = setInterval(function() {
counter++;
if (counter === howManyTimes) {
clearInterval(interval);
}
// do something
console.log(counter, 'iteration')
}, howOften)
}
// run the function
checkInIntervals(10, 2000);
Inside the interval the counter is incremented and when it's equal the the desired number of iterations, the interval is cleared and the execution stops.

How do I minify the following series of for loops into a less compact code?

I have the following code which follows a pattern of loops , I have a feeling that code can be minified to a recursion like code or any less ugly looking code , but I am unable to figure it out.
I want to run six loops one inside the other from 1000 to 10000 in javascript, I look to minify the code if possible.
I am beginner in coding , but all kinds of methods are acceptable for me.
I am updating the code as previous code might get ambigous for some users.
function dummyFunc(x,y){
if( some logic for x == some logic for y){
return true;
}
return false;
}
for(var i = 1000;i < 10000;i++){
for(var j = 1000;j < 10000;j++){
if(dummyFunc(i,j)){
for(var k = 1000;k < 10000;k++){
if(dummyFunc(j,k)){
for(var l = 1000;l < 10000;l++){
if(dummyFunc(k,l)){
for(var m = 1000;m < 10000;m++){
if(dummyFunc(l,m)){
for(var n = 1000;n < 10000;n++){
if(dummyFunc(m,n)){
break;
}
}
}
}
}
}
}
}
}
}
}
You could extract the for loop into a function:
function range(start, end, callback) {
for(let i = start, start < end, i++)
callback(i);
}
That can be used as:
range(1000, 10000, i => {
range(1000, 10000, j => {
range(1000, 10000, k => {
range(1000, 10000, l => {
range(1000, 10000, m => {
range(1000, 10000, n => {
console.log(i, j, k, l, m, n);
});
});
});
});
});
To simplify that even further, you could use a generator that yields an array of values which you can destructured:
function* ranges(start, end, repeats) {
if(repeats > 1) {
for(const values of ranges(start, end, repeats - 1)) {
for(const value of ranges(start, end, 0)) {
yield values.concat(value);
}
}
} else {
for(let i = start; i < end; i++)
yield [i];
}
}
That can be used as:
for(const [i, j, k, l, m, n] of ranges(1000, 10000, 6)) {
console.log(i, j, k, l, m, n);
}
Use the following code. Instead of returning true or false, you should start the loop inside the dummyFunc, this will call the function recursively.
function dummyFunc(x,y){
if( some logic for x == some logic for y)
for(var i = 1000;i < 10000;i++)
for(var j = 1000;j < 10000;j++)
dummyFunc(i,j);
}
for(var i = 1000;i < 10000;i++)
for(var j = 1000;j < 10000;j++)
dummyFunc(i,j);
To add clarity to how recursive function is working (writing in usual recursive function style - return is some condition is satisfied else call function again) you may write it as follows
function dummyFunc(x,y){
if( !(some logic for x == some logic for y))
return;
for(var i = 1000;i < 10000;i++)
for(var j = 1000;j < 10000;j++)
dummyFunc(i,j);
}
for(var i = 1000;i < 10000;i++)
for(var j = 1000;j < 10000;j++)
dummyFunc(i,j);
Here is your complete simplified code
function getDeeper(i, j, start, end, level) {
if(j === end && (i = (i+1)) && (j = start)) {}
if(dummyFunc(i, j)) {
if(level === 4) return;
getDeeper(j, start, start, end, ++level);
}
getDeeper(i, ++j, start, end, level);
}
getDeeper(1000, 1000, 1000, 10000, 0);
Since your question is How do I minify the following series of for loops into a less compact code? and is not specifically asking for a better code example I will instead show you how to fish instead of giving you the fish.
You need to read about Structured program theorem:
It states that a class of control flow graphs (historically called
charts in this context) can compute any computable function if it
combines subprograms in only three specific ways (control structures).
These are
Executing one subprogram, and then another subprogram (sequence)
Executing one of two subprograms according to the value of a boolean expression (selection)
Repeatedly executing a subprogram as long as a boolean expression is true (iteration)
Also worth reading is Flow Diagrams, Turing Machines And Languages With Only Two Formation Rules by Corrado Bohm and Giuseppe Jacopini for whom the theorem is named after.
So if I understand you code correctly then while the example looks like a long task when computed as such
If we assume that your browser makes 1000 * 1000 iterations per
second, this will take 1000 * 1000 * 1000 * 1000 seconds to complete.
That is very long (317 centuries)
as noted by Jonas Wilms,
from my extensive experience with predicates which is that a predicate will only return true or false and if you know that once it is true you can stop processing because you have the result. On the other hand if the result is false then you need to process all of the results. The real trick is not to brute force through all of the values but to quickly eliminate combinations of inputs that don't help lead to a solution.
While I don't know exactly what you are trying to do, I would also take a look at Binary decision diagram and/or Constraint satisfaction which are great ways to simplify complex problems.
Based on the code you provided, you could simplify with the following:
function dummyFunc(x,y){
if( some logic for x == some logic for y){
return true;
}
return false;
}
for(var i = 1000;i < 10000;i++) {
for(var j = 1000;j < 10000;j++) {
if(dummyFunc(i,j)) {
break;
}
}
}
You could argue I am taking your example too literally, but hopefully it either answers your question or illustrates why you need a better example to get a better answer.
the same for loop repeated each time
so you can move it inside the function
function dummyFunc(x) {
for (y = 1000; y < 10000; y++) {
if (some logic for x == some logic for y) {
return y;
}
}
return false;
}
for (var i = 1000; i < 10000; i++) {
if (j = dummyFunc(i)) {
if (k = dummyFunc(j)) {
if (l = dummyFunc(k)) {
if (m = dummyFunc(l)) {
if (n = dummyFunc(m)) {
break;
}
}
}
}
}
}
this solution if you need i,j,k,l,m and n variables
if you don't need those variables
by using recursive function
this solution gives the equal to n variable in your question
function dummyFunc(x) {
numberOfLoops = 6;
for (y = 1000; y < 10000; y++) {
if (some logic forr x == some logic forr y) {
if (numberOfLoops == 0) {
return n;
}
n=dummyFunc(x)
numberOfLoops--;
}
}
return false;
}
for (var i = 1000; i < 10000; i++) {
n = dummyFunc(i)
}
I haven't check my code , your comments would be helpful
I'm still not sure why exactly you would want to do this, but below are two potential solutions depending on the behavior you want at the "break". Neither is very pretty, but they both work for the problem described.
Solution (A) - breaks only the inner-most loop, which would exactly match the behavior described in the question.
function loopenstein(minn, maxx, maxDepth, dummyCall) {
function recursiveLoop(i, minn, maxx, depth, dummyCall) {
for (var j = minn; j < maxx; j++)
if (dummyFunc(i, j)) {
if (depth <= 0) {
console.log("break me daddy...")
return;
}
recursiveLoop(j, minn, maxx, depth - 1, dummyCall))
}
}
for (var i = minn; i < maxx; i++) {
recursiveLoop(i, minn, maxx, maxDepth, dummyCall))
}
}
/* usage */
loopenstein(1000, 10000, 6, dummyFunc)
Solution (B) - breaks completely out of all loops once dummyFunc returns true for the 6th loop.
function loopenstein(minn, maxx, maxDepth, dummyCall) {
//recursive helper function
function loopensteinHelper(i, minn, maxx, depth, dummyCall) {
for (var j = minn; j < maxx; j++)
if (dummyFunc(i, j)) {
if (depth <= 0) {
console.log("break me daddy...")
return true;
} else if (loopensteinHelper(j, minn, maxx, depth - 1, dummyCall)) {
return true;
}
return false;
}
for (var i = minn; i < maxx; i++) {
if (loopensteinHelper(i, minn, maxx, maxDepth, dummyCall)) {
return true;
}
}
return false;
}
/* usage */
var isFound = loopenstein(1000, 10000, 6, dummyFunc)
I would recommend to use promise. Below is the modified version of the code:
var looper = function(start = 1000, end = 10000) {
return new Promise(function(resolve, reject) {
console.log('Starting');
for (; start <= end; start++) {
// Your computation goes here
}
resolve();
});
}
Now if you want to run a loop 3 times use it like:
looper().then(looper()).then(looper())
If you need to run loop 4 times use as:
looper().then(looper()).then(looper()).then(looper())
You can learn more about Promises here

How to use continue in a loop to change a value

I am trying to have a loop that gives me values from 1 to 30. However every number divisible by 10 I want to hard code the value to the corresponding word. Example would be value 10 = "Ten", 20 = "Twenty" and so on.
I tried to do this with 'continue', however my displayed results do not go pass "Ten".
for (i = 0; i <= 30; i++) {
if (i == 10) {
i = "Ten";
continue;
} if (i == 20) {
i = "Twenty";
continue;
}
console.log(i);
}
Results
Am I going on about it the right way? Could you please offer some hints so I can figure this out. Thank you,
I tried this initially. But didn't work.
for (i = 0; i <= 30; i++) {
if (i == 10) {
i = "Ten";
} if (i == 20) {
i = "Twenty";
}
console.log(i);
}
Just get rid of the continue statements. They cause the loop to immediately skip to the end and start another iteration. Thus, your console output statement is skipped. Also, you don't want to touch the loop variable, and it wouldn't hurt to have an else. Something like this:
var result;
for (i = 0; i <= 30; i++) {
if (i == 10) {
result = "Ten";
} else if (i == 20) {
result = "Twenty";
} else {
result = i;
}
console.log(result);
}
Or you could just log the desired output directly in each branch of the if/else chain:
for (i = 0; i <= 30; i++) {
if (i == 10) {
console.log("Ten");
} else if (i == 20) {
console.log("Twenty");
} else {
console.log(i);
}
}
I dont think you can change i and expect it to work as usual. hence as soon as you change the value to "TEN", the loop terminates..!!!!
When the counter i gets to ten, you are replacing it with a string, so when the control flow reaches the i++ part, your loop fails. What you should do is assign the value to be printed to another variable that is only used inside the body of the loop.

How to implement .map() using for()?

I have these array and variable:
var arr = [['one','blue'], ['two','red'], ['three','green']]
var variable = 'thre';
Also I have this code:
arr.map(function(x){
if(x[0].indexOf(variable) >= 0)
{
alert('Number is found');
}
});
As you know, map works as a loop, and in the array above, there is three items and then map executes its statement 3 times. So that alert will be run.
Now I'm trying to limit the mapping, I mean I want to execute a statement 2 times. So I user for() like this:
for ( var c = 0; c < 2; c++ ) {
if ( arr[c][0].indexOf(variable) >= 0 )
{
alert('number is found');
}
}
But ^ doesn't work, It gives me this error:
Uncaught TypeError: Cannot read property '0' of undefined {in line 2}
How can I fix it?
EDIT: Here is my code in reality:
ZippedArray.map(function(x){
if(x[0].indexOf(name) >= 0)
{
MatchesNames.push(x[0]);
MatchesIds.push(x[1]);
}
});
I want this output:
MatchesNames = MatchesNames.slice(0,2);
MatchesIds = MatchesIds.slice(0,2);
How to limit .map() ? I want something like break; after 2 times.
Based on your comments, it seems you want to loop until you've found two matches in the if condition.
In that case, you can use .some(), which will halt the loop as soon as you return true (or any truthy value).
ZippedArray.some(function(x){
if(x[0].indexOf(name) >= 0)
{
MatchesNames.push(x[0]);
MatchesIds.push(x[1]);
}
return MatchesNames.length == 2; // Breaks when this returns `true`
});
This example assumes that MatchesNames was empty before you called .some().
If there could be other items in the array, and you just want to push two more in at the most, then you could keep a count.
var found = 0;
ZippedArray.some(function(x){
if(x[0].indexOf(name) >= 0)
{
MatchesNames.push(x[0]);
MatchesIds.push(x[1]);
found++;
}
return found == 2;
});
If you want to use a traditional for loop, then do this:
var found = 0;
for (var i = 0; i < ZippedArray.length; i++) {
var x = ZippedArray[i];
if(x[0].indexOf(name) >= 0)
{
MatchesNames.push(x[0]);
MatchesIds.push(x[1]);
found++;
}
if (found == 2) {
break;
}
}
The code you posted does not throw an error.
But when you're limiting the loop count of iterating an array, you should add a range check for the index:
for (var c = 0; c < 2 && c < arr.length; c++) {
// or alternatively
for (var c = 0, l = Math.min(2, arr.length); c < l; c++) {

Recursive function or loop in javascript?

I am trying to write a recursive function, but I am completely lost as to how to implement it. I currently have the following:
function change(p){
// code for function
}
var c1 = change(start);
var c2 = change(c1);
var c3 = change(c2);
// etc. etc.
Is there any way to do this with a while loop? For example:
while(currentResultofFunction != goal)
nestedly loop through as before until reaches true
function change(p) {
if (p != 1) { // your condition
change(p);
} else return p;
}
What about:
var val = start;
while(val) //or while val != goal
val = change(val);
What you are doing, is not recursive. You maybe mean iterative.
You can loop through the variables in this way:
var n = 2;
for (var i = 1; i <= n; i++) {
if (i == 1) window['c1'] = change(start);
else window['c' + i] = change(window['c' + (i - 1)]);
}

Categories

Resources