Is there a way to break from the forEach iterator in Ember?
I tried to return false in the callback (a la jQuery) but it does not work.
Thanks!
PJ
You can use Array#some or Array#every
[1,2,3].some(function(element) {
return true; // Break the loop
});
[1,2,3].every(function(element) {
return false; // Break the loop
});
More informations here
Ember uses the native Array.prototype.forEach if it's available, and emulates it if not. See https://github.com/emberjs/ember.js/blob/v1.0.0-rc.1/packages/ember-metal/lib/array.js#L45.
JavaScript's forEach doesn't support breaking. See https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
Nope, I dont think so cfr James, looking at the foreach code, you can see that it uses a for loop under the hood. You can throw an exception, but thats like writing spagetti code.
But it might be possible, you can do a feature request at github? Or write your own implementation that breaks in the for loop.
Use Array#find and return true to break out of the loop.
Using toArray can potentially remove the order of the array, which sort of defeats the purpose. You could use a normal for loop but use objectAt to make it work for you.
var emberArray = [ ... Array of Ember objects ... ],
min = 3,
max = emberArray.get('length'),
targetObject;
for( var i = min; i < max; i++ ){
targetObject = emberArray.objectAt( i );
if( targetObject.get('breakHere') ) {
break;
}
}
This has the added benefit of allowing you to start at a certain index, so you can loop through the smallest number of items.
Related
I have issues with Google app script IF condition.
Problem i am facing its not returning value TRUE rather going to next/ Else statements.
Code i am having:
const numberOfRowsToUpdate = deliveryDate.length;
// For each item making the for loop to work
for (i=0 ; i < numberOfRowsToUpdate;i++) {
debugger;
var dp = depositAmount[i];
if(dp!==""|| dp!==0 || dp !==null || dp!==isblank())
{ .... <statements>
}
}
I want to check whether particular cell of the array is empty / zero / returning null value.
thanks in advance for the help.
SUGGESTION
I have used a similar script I'm using for a spreadsheet in which I need to search through every row for some data, but obviously adpating it to your case, and since I don't have your full code (and still can't comment asking for more info due to my recent joining in SO), I had to simplify it, in hope it will work for you.
What I did was use your incrementing i index from the for loop and use it to scan every row, while adjusting it to fit your array index, because we can't have i = 0 as a row index, and it would skip the first value on the array if left as i = 1).
SCRIPT
function test(){
const n = 6;
var depositAmount = [7,2,0,2,0,8];
// For each item making the for loop to work
var ss = SpreadsheetApp.getActive();
Logger.log(ss.getName());
for (var i=1 ; i <= n ;i++) {
debugger;
ss.getRange("A"+i).setValue(1);
var dp = depositAmount[i-1];
Logger.log(dp)
if(dp != "" || dp != 0 /*|| dp != null || dp != isblank()*/)
{
ss.getRange("B"+i).setValue(dp);
}
else
{
ss.getRange("C"+i).setValue("VOID")
Logger.log(i-1+"th index of array is "+ss.getRange("C"+i).getValue());
}
}
};
RESULTS
After running it with the four original conditions you used, i didn't get the expected result, as you must have, leading to this:
.
While studying your original code, I stumbled upon this question about the differences between == and ===, as well as != and !==.
So before I used this in our favor, I tried the old trial and error method, using only one condition at a time, and then stacking them up. Not only I managed to find out the !== operator didn't work properly for this case, but also the comparison with null and the isblank() function (at least in my case, because i haven't defined it, and I'm not sure it is a built-in function) also don't work with either operator.
Therefore, using the != operator helps you better than the strict !==.
The result of the final script is that:
.
NOTES
I also tried using a null value within the array ([7,2,0,2,,8]), but it would always break away from the loop, never scanning the whole array, and I don't know how to circle that.
Here is the Execution Log for this script:
EDIT
While fooling around, I found this question and the answer by Etienne de Villers might be even faster to apply, or at least more useful for your purposes.
I was just wondering about something that popped into my mind while writing some code.
for (int i = 0; i < num_bits; i++) {
if (bits.at(i) == 0) {
}
else if (bits.at(i) == 1) {
}
}
In this code, bits is a string and num_bits is the length of the string.
In this case, would the program run string.at(i) at both the if and the `else if``, or would it run it once and then store it somewhere and use it at both of the statements? I don't know if the question was clear enough, but thanks for any answer.
Think about it. How would the engine know that every call to that function would produce the same result?
It wil run the function whenever you call it, so for this example 2 times. You can declare it at the top of the for loop or use a foreach if you need to do more heavy operations.
I'm using action script and I have an array with more than 400.000 strings and now i'm using a loop and apply a regex to each item of the array to check if it's valid or not. In case it's valid, i put such item in a result array.
this process take too long, so it's a nuisance because all the process must executed many times.
I've been thinking about if there is any other way (faster) i could use for applying the regex to all items without using a loop.
Anyone could give me an idea?
EDIT
Here I attach the code used:
var list:Array;
var list_total:Array = new Array;
var pattern:String = '^['+some_letters+']{'+n+'}$';
var cleanRegExp:RegExp = new RegExp(pattern, 'gi');
for (var i:int=0; i<_words.length; i++) {
list = _words[i].match(cleanRegExp);
if (list != null)
for (var j:int=0; j < list.length; j++)
list_total.push(list[j]);
}
Thanks.
This is not a complete answer, but may help you optimize your code.
Try to do operations in your loop that are as efficient as possible. Time them using the global getTimer() function so you can compare which methods are the most efficient. When measuring/comparing, you may want to trigger your code many times, so that these differences are noticeable.
// before test
var startTime:Number = getTimer();
// do the expensive operation
var endTime:Number = getTimer();
trace("operation took ", endTime - startTime, " milliseconds.");
For example, one improvement is inside a for loop, is to not query the array for it's length each time:
for (var i:int = 0; i < myArray.length; i++)
Instead, store the length in a local variable outside of the array and use that:
var length:int = myArray.length;
for (var i:int = 0; i < length; i++)
The difference is subtle, but accessing the length from the local variable will be faster than getting it from the Array.
Another thing you can test is the regular expression itself. Try to come up with alternate expressions, or use alternate functions. I don't recall the specifics, but in one project we determined (in our case) that using the RegEx.test() method was the fastest way to do a comparison like this. It's likely that this may be as quick as String.match() -- but you won't know unless you measure these things.
Grant Skinner has some awesome resources available on his site. They are worth reading. This slide show/presentation on performance is worth looking at. Use the arrow keys to change slides.
Edit
Without hearing Grant's presentation, the initial slides may not seem that interesting. However, it does get very interesting (with concrete code examples) around slide #43: http://gskinner.com/talks/quick/#43
I do not think there is any good way to avoid using a loop.
The loop could be optimized further though.
Like someone already suggested read the array length to a var so the loop doesn't have to check length each iteration.
Instead of the nested loop use concat to join the list array to the lists_total. I'm not sure if this is actually faster. I guess it depends on how many matches the regexp gets.
Here is the modified code.
var list:Array;
var list_total:Array = new Array;
var pattern:String = '^['+some_letters+']{'+n+'}$';
var cleanRegExp:RegExp = new RegExp(pattern, 'gi');
var wordsLength:int = _words.length;
for (var i:int=0; i<wordsLength; i++) {
list = _words[i].match(cleanRegExp);
if (list != null)
lists_total = lists_total.concat(list);
}
Guys, I have the following code that is inside a big while loop that iterates over a tree. This is as fast as I can get this routine but I have to use a goto. I am not fundamentally against goto but if I can avoid them I would like to. (I am not trying to start a flame war, please.)
The constraints:
The current=current->child() is expensive (it's a shared_ptr) so I'd like to minimize the use of that operation at all cost.
After the operation current should be the last child it found.
cnt must count each child it encounters.
cnt++ will be replaced by some other operation (or several operations) and should only appear once :)
the code:
insideloopy:
cnt++;
if ( current->hasChild() )
{
current = current->child();
goto insideloopy;
}
Edit: Sorry guys, originally forgot to mention cnt++ should only appear once. It will be some kind of operation on the node, and should thus only be there one time. I'm also trying to avoid making that another function call.
Original answer
Assuming this is C or C++:
while (cnt++, current->hasChild())
{
current = current->child();
}
I'm not a big fan of the comma operator usually, but I don't like repeating myself either :)
Updated 'fun' answer
After learning that cnt++ is actually some multiline operation, this particular syntax would be less than ideal. Something more along the lines of your accepted answer would be better.
If you want to be really funky, this would also work:
do
{
cnt++;
} while (current->hasChild() && (current = current->child()));
Now I feel really dirty though, with my abusing the short circuiting on the && operator :)
Sane answer
Exercises in compactness aside and striving for readable code, I'm forced to conclude that one of the existing answers is best suited (I'm just including this for completeness' sake):
while (true)
{
cnt++;
if (!current->hasChild()) break;
current = current->child();
}
The while (true) will be optimized by the compiler into a regular infinite loop, so there is only one conditional statement (if you care about that).
The only thing going against this solution is if your node operation was a long piece of code. I don't mind infinite loops so much, as long as I can see where they terminate at a glance. Then again, if it were really long, it should be a function anyway.
cnt++;
while(current->hasChild())
{
cnt++;
current = current->child();
}
EDIT:
If you only want cnt++ to be in your code once:
while(true)
{
cnt++;
if(current->hasChild())
current = current->child();
else
break;
}
insideloopy:
cnt++;
if ( current->hasChild() )
{
current = current->child();
goto insideloopy;
}
I love infinite loops.
while (true) {
cnt++;
if (!current->hasChild()) break;
current = current->child();
}
Of course you can do it in many other ways (see other answers). do while, put the check in the while, etc. In my solution, I wanted to map nearly to what you are doing (an infinite goto, unless break)
You can use break to get out of the loop in the middle of the code:
while (true) {
cnt++;
if (!current->hasChild()) break;
current = current->child();
}
while (current->hasChild())
{
cnt++;
current = current->child();
}
Or am I missing something?
for(cnt++ ; current->hasChild() ; cnt++) {
current = current->child();
}
I'd investigate the possibility of making current->child() return NULL when it has no child if it doesn't already -- that seems the best possible result and leaving it undefined in this case seems error prone -- and then use:
for (; current; current = current->child())
{
cnt++;
}
No break statements:
notDone=true;
while(notDone){
cnt++;
if ( current->hasChild() ){
current = current->child();
} else {
notDone=false;
}
}
I find myself writing code that looks like this a lot:
set<int> affected_items;
while (string code = GetKeyCodeFromSomewhere())
{
if (code == "some constant" || code == "some other constant") {
affected_items.insert(some_constant_id);
} else if (code == "yet another constant" || code == "the constant I didn't mention yet") {
affected_items.insert(some_other_constant_id);
} // else if etc...
}
for (set<int>::iterator it = affected_items.begin(); it != affected_items.end(); it++)
{
switch(*it)
{
case some_constant_id:
RunSomeFunction(with, these, params);
break;
case some_other_constant_id:
RunSomeOtherFunction(with, these, other, params);
break;
// etc...
}
}
The reason I end up writing this code is that I need to only run the functions in the second loop once even if I've received multiple key codes that might cause them to run.
This just doesn't seem like the best way to do it. Is there a neater way?
One approach is to maintain a map from strings to booleans. The main logic can start with something like:
if(done[code])
continue;
done[code] = true;
Then you can perform the appropriate action as soon as you identify the code.
Another approach is to store something executable (object, function pointer, whatever) into a sort of "to do list." For example:
while (string code = GetKeyCodeFromSomewhere())
{
todo[code] = codefor[code];
}
Initialize codefor to contain the appropriate function pointer, or object subclassed from a common base class, for each code value. If the same code shows up more than once, the appropriate entry in todo will just get overwritten with the same value that it already had. At the end, iterate over todo and run all of its members.
Since you don't seem to care about the actual values in the set you could replace it with setting bits in an int. You can also replace the linear time search logic with log time search logic. Here's the final code:
// Ahead of time you build a static map from your strings to bit values.
std::map< std::string, int > codesToValues;
codesToValues[ "some constant" ] = 1;
codesToValues[ "some other constant" ] = 1;
codesToValues[ "yet another constant" ] = 2;
codesToValues[ "the constant I didn't mention yet" ] = 2;
// When you want to do your work
int affected_items = 0;
while (string code = GetKeyCodeFromSomewhere())
affected_items |= codesToValues[ code ];
if( affected_items & 1 )
RunSomeFunction(with, these, params);
if( affected_items & 2 )
RunSomeOtherFunction(with, these, other, params);
// etc...
Its certainly not neater, but you could maintain a set of flags that say whether you've called that specific function or not. That way you avoid having to save things off in a set, you just have the flags.
Since there is (presumably from the way it is written), a fixed at compile time number of different if/else blocks, you can do this pretty easily with a bitset.
Obviously, it will depend on the specific circumstances, but it might be better to have the functions that you call keep track of whether they've already been run and exit early if required.