Here is the test I am trying to pass:
describe("occur", function() {
var getVal = function(i) { return i; };
var even = function(num) { return num % 2 === 0; };
it("should handle an empty set", function() {
expect(occur([], getVal) ).toEqual(true);
});
it("should handle a set that contains only true values", function() {
expect(occur([true, true, false], getVal)).toEqual(false);
});
it("should handle a set that contains one false value", function() {
expect(occur([true, true, true], getVal)).toEqual(true);
});
it("should handle a set that contains even numbers", function() {
expect(occur([0, 8, 32], even)).toEqual(true);
});
it("should handle a set that contains an odd number", function() {
expect(occur([0, 13, 68], even)).toEqual(false);
});
});
Here is my code:
var forEach = function(array, action){
for (var i = 0; i < array.length; i ++){
action(array[i]);
}
};
var occur = function(array, blah){
forEach(array, function(el){
if(!blah(el)){
return false;
}
});
return true;
};
What I believe I am doing in my occur function:
Taking parameters(an array and a function
Iterating over the array (in the forEach)
If blah(el) isn't true, return false (shouldn't this break the loop and return false whenever there the function passed in evaluates to false?
return true if there aren't any false values
**I do not have a case currently implemented for an empty array.
Am I missing a trick with how return works? I provided a repl.it session of it below (link). I included a console.log inside my if statement and it does log 'false' when a value is false but the return value still doesn't output or break the loop.
http://repl.it/NjH/1
The core issue is that return always exits the nearest enclosing function - and no other.
var occur = function(array, blah){ // <-- "outer" function
forEach(array, function(el){ // <-- callback to forEach / "enclosing" function
if(!blah(el)){
// This returns from the callback/enclosing function; it has no
// bearing on the outer function.
return false;
}
});
return true;
};
Barring changing approaches, this problem can be solved with using a variable.
var occur = function(array, blah){
var ret = true;
forEach(array, function(el){
if(!blah(el)){
// Set the closed-over variable to false, so that when the return
// in the outer function is reached the correct value will be returned.
// (forEach will still iterate over every remaining item)
ret = false;
}
});
return ret;
};
Now, my recommendation is to use something like Array.some (which is in ES5.1 and supported in IE9+ and every modern browser of note).
var occur = function(array, blah){
var any = array.some(function(el){
if(!blah(el)){
return true;
}
});
return !any;
};
But really, changing the conditions (negations inside/outside and some to every):
var occur = function(array, blah){
return array.every(function(el){
return blah(el);
});
};
forEach does not return a value in Javascript-- when you return false, you're simply returning false from forEach's callback. The value is ignored.
Instead, you could try Array.every() if you're using a compatible implementation like Node/Webkit/something that supports ECMAScript 5.
Otherwise, set a semaphore variable outside the forEach, and set it to false if blah(el) returns false. Then check the value of the variable after the forEach is complete.
You aren't missing a trick about return, you're missing one about .forEach.
For each basically looks like this:
function forEach (action) {
var arr = this,
i = 0, l = arr.length;
for (; i < l; i += 1) {
action(arr[i], i, arr);
}
}
There's more to it than just that, but really, that's what it's doing.
So if action() has a return statement in it (and even if it doesn't, it just returns undefined, it doesn't matter to the loop at all.
It says "forEach" and what it will get you is one pass through every single item in the array (that exists at the time the function is called).
Related
How do I break out of a jQuery each loop?
I have tried:
return false;
in the loop but this did not work. Any ideas?
Update 9/5/2020
I put the return false; in the wrong place. When I put it inside the loop everything worked.
To break a $.each or $(selector).each loop, you have to return false in the loop callback.
Returning true skips to the next iteration, equivalent to a continue in a normal loop.
$.each(array, function(key, value) {
if(value === "foo") {
return false; // breaks
}
});
// or
$(selector).each(function() {
if (condition) {
return false;
}
});
According to the documentation return false; should do the job.
We can break the $.each() loop [..] by making the callback function
return false.
Return false in the callback:
function callback(indexInArray, valueOfElement) {
var booleanKeepGoing;
this; // == valueOfElement (casted to Object)
return booleanKeepGoing; // optional, unless false
// and want to stop looping
}
BTW, continue works like this:
Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
I came across the situation where I met a condition that broke the loop, however the code after the .each() function still executed. I then set a flag to "true" with an immediate check for the flag after the .each() function to ensure the code that followed was not executed.
$('.groupName').each(function() {
if($(this).text() == groupname){
alert('This group already exists');
breakOut = true;
return false;
}
});
if(breakOut) {
breakOut = false;
return false;
}
I created a Fiddle for the answer to this question because the accepted answer is incorrect plus this is the first StackOverflow thread returned from Google regarding this question.
To break out of a $.each you must use return false;
Here is a Fiddle proving it:
http://jsfiddle.net/9XqRy/
I know its quite an old question but I didn't see any answer, which clarify that why and when its possible to break with return.
I would like to explain it with 2 simple examples:
1. Example:
In this case, we have a simple iteration and we want to break with return true, if we can find the three.
function canFindThree() {
for(var i = 0; i < 5; i++) {
if(i === 3) {
return true;
}
}
}
if we call this function, it will simply return the true.
2. Example
In this case, we want to iterate with jquery's each function, which takes anonymous function as parameter.
function canFindThree() {
var result = false;
$.each([1, 2, 3, 4, 5], function(key, value) {
if(value === 3) {
result = true;
return false; //This will only exit the anonymous function and stop the iteration immediatelly.
}
});
return result; //This will exit the function with return true;
}
"each" uses callback function.
Callback function execute irrespective of the calling function,so it is not possible to return to calling function from callback function.
use for loop if you have to stop the loop execution based on some condition and remain in to the same function.
I use this way (for example):
$(document).on('click', '#save', function () {
var cont = true;
$('.field').each(function () {
if ($(this).val() === '') {
alert('Please fill out all fields');
cont = false;
return false;
}
});
if (cont === false) {
return false;
}
/* commands block */
});
if cont isn't false runs commands block
I'm attempting to create a function which accepts an array and a callback function. The function should return true if all values in the array passed to the callback return true, otherwise, return false. But I'm not sure what I'm doing incorrectly
const every = function(arr, callback) {
arr.forEach(function(element) {
if(!callback(element)) {
return false
}
})
return true
};
every([1, 2, 3, 4, 5], function(val) {
return val < 2
});
expected results => false
but I'm getting true.
I would recommend using a simple for loop:
const every = (arr, callback) => {
for (let i = 0; i < arr.length; i++){
if (callback(arr[i]) === false){
return false;
}
}
return true;
};
console.log(every([1, 2, 3, 4, 5], function(val){return val < 2}));
Returning false from the forEach callback will not also cause the every function to return. Instead it will simply continue the forEach iterator.
The most easy solution to your problem would be a for...of loop, since it allows you to use a return pattern similar to your snippet:
const every = function(arr, callback) {
for (const element of arr) {
if (!callback(element)) {
return false;
}
}
return true;
};
console.log(every([1, 2, 3, 4, 5], function(val) {
return val < 2;
}));
Note: By using a loop construct every returns early. The forEach method of arrays always runs until all array elements are visited, but the loop breaks immediately after one element fails the test. A regular for loop would give you the same performance benefit.
You could potentially use reduce() for this. If you base your reduction on the truth and the result of the callback, it will remain true so long as the callback is true. Once a callback is false, the check for truth in the conditional will short circuit the logic and the callback will not execute anymore. It will loop through all the elements though.
It also returns true for an empty array, which seems to match your original logics intent.
const every = function(arr, callback) {
return arr.reduce(function(truth, element){
return truth && callback(element);
}, true);
};
console.log(
every([1, 2, 3, 4, 5], function(val){return val < 2})
);
console.log(
every([], function(val){return val < 2})
);
arr.forEach(function(element) {
return false
})
Its the inner function returning false, which have no effect for the outer function (in this situation)
you should create a new variable inside the outer function and instead of returning false in the inner function, change the variable
at the end just return the variable
const every = function(arr, callback) {
let isEvery = true
arr.forEach(function(element) {
if(!callback(element)) { // or just isEvery = isEvery && statement
isEvery = false
}
})
return isEvery
};
How do I break out of a jQuery each loop?
I have tried:
return false;
in the loop but this did not work. Any ideas?
Update 9/5/2020
I put the return false; in the wrong place. When I put it inside the loop everything worked.
To break a $.each or $(selector).each loop, you have to return false in the loop callback.
Returning true skips to the next iteration, equivalent to a continue in a normal loop.
$.each(array, function(key, value) {
if(value === "foo") {
return false; // breaks
}
});
// or
$(selector).each(function() {
if (condition) {
return false;
}
});
According to the documentation return false; should do the job.
We can break the $.each() loop [..] by making the callback function
return false.
Return false in the callback:
function callback(indexInArray, valueOfElement) {
var booleanKeepGoing;
this; // == valueOfElement (casted to Object)
return booleanKeepGoing; // optional, unless false
// and want to stop looping
}
BTW, continue works like this:
Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
I came across the situation where I met a condition that broke the loop, however the code after the .each() function still executed. I then set a flag to "true" with an immediate check for the flag after the .each() function to ensure the code that followed was not executed.
$('.groupName').each(function() {
if($(this).text() == groupname){
alert('This group already exists');
breakOut = true;
return false;
}
});
if(breakOut) {
breakOut = false;
return false;
}
I created a Fiddle for the answer to this question because the accepted answer is incorrect plus this is the first StackOverflow thread returned from Google regarding this question.
To break out of a $.each you must use return false;
Here is a Fiddle proving it:
http://jsfiddle.net/9XqRy/
I know its quite an old question but I didn't see any answer, which clarify that why and when its possible to break with return.
I would like to explain it with 2 simple examples:
1. Example:
In this case, we have a simple iteration and we want to break with return true, if we can find the three.
function canFindThree() {
for(var i = 0; i < 5; i++) {
if(i === 3) {
return true;
}
}
}
if we call this function, it will simply return the true.
2. Example
In this case, we want to iterate with jquery's each function, which takes anonymous function as parameter.
function canFindThree() {
var result = false;
$.each([1, 2, 3, 4, 5], function(key, value) {
if(value === 3) {
result = true;
return false; //This will only exit the anonymous function and stop the iteration immediatelly.
}
});
return result; //This will exit the function with return true;
}
"each" uses callback function.
Callback function execute irrespective of the calling function,so it is not possible to return to calling function from callback function.
use for loop if you have to stop the loop execution based on some condition and remain in to the same function.
I use this way (for example):
$(document).on('click', '#save', function () {
var cont = true;
$('.field').each(function () {
if ($(this).val() === '') {
alert('Please fill out all fields');
cont = false;
return false;
}
});
if (cont === false) {
return false;
}
/* commands block */
});
if cont isn't false runs commands block
I have a few functions in two different files that are all linked together by function calls they are as follows
FILE 1:
function getFunction(func){
}
FILE 2:
function Numbers(one, two) {
return (one*two);
}
var func = getFunction(Numbers);
and these are called by:
func(input_array);
my array has values 1,3,5,7,9 and I need func(input_array) to return 3,15,35,63,9 (the last value loops back to the first value)
basically what I am trying to do is have getFunction return a function such that these values are calculated. I am having trouble because I can't wrap my mind about sending and returning functions. I don't know how to access the array if it isn't sent into the function. Let me know if I need to clarify anything.
function getFunction(callback) {
return function(array) {
return array.map(function(cur, index) {
return callback(cur, array[(index+1) % array.length]);
});
};
}
getFunction returns a closure over the callback parameter, which is the function that you want to call. The closure receives the array parameter, and it calls the callback in a loop over the array using array.map. The % modulus operator performs the wraparound that you want.
Another way to write this that may be clearer is:
function getFunction(callback) {
return function(array) {
var result = [];
for (var i = 0; i < array.length; i++) {
j = (i+1) % array.length; // Next index, wrapping around
result.push(callback(array[i], array[j]));
}
return result;
};
}
var func = getFunction(Numbers);
console.log(func([1,3,5,7,9])); // Logs [3,15,35,63,9]
here is simple function that returns what you need
function Numbers(x) {
output_array=[];
for(i=0;i<x.length;i++){
if(x[i+1]==undefined){
output_array.push(x[i]);
}
else{
output_array.push(x[i]*x[i+1]);
}
}
return output_array;
}
var input_array=[1,3,5,7];
var num = Numbers(input_array);
console.log(num);
OR if you need it in the way function calling another function
and than returning the result use this
function getFunction(Numbers,input_array){
return Numbers(input_array);
}
function Numbers(x) {
output_array=[];
for(i=0;i<x.length;i++){
if(x[i+1]==undefined){
output_array.push(x[i]);
}
else{
output_array.push(x[i]*x[i+1]);
}
}
return output_array;
}
var input_array=[1,3,5,7];
var num = getFunction(Numbers,input_array);
console.log(num);
Object.prototype.e = function() {
[].forEach.call(this, function(e) {
return e;
});
};
var w = [1,2];
w.e(); // undefined
But this works if I use alert instead
// ...
[].forEach.call(this, function(e) {
alert(e);
});
// ...
w.e(); // 1, 2
I realize this is an old question, but as it's the first thing that comes up on google when you search about this topic, I'll mention that what you're probably looking for is javascript's for.. in loop, which behaves closer to the for-each in many other languages like C#, C++, etc...
for(var x in enumerable) { /*code here*/ }
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/for...in
http://jsfiddle.net/danShumway/e4AUK/1/
A couple of things to remember :
for..in will not guarantee that your data will be returned in any particular order.
Your variable will still refer to the index, not the actual value stored at that index.
Also see below comments about using this with arrays.
edit: for..in will return (at the least) added properties to the prototype of an object. If this is undesired, you can correct for this behavior by wrapping your logic in an additional check:
for(var x in object) {
if(object.hasOwnProperty(x)) {
console.log(x + ": " + object[x]);
}
}
Your example is a bit odd, but as this question is becoming the canonical "return from forEach" question, let's use something simpler to demonstrate the problem:
Here, we have a function that checks the entries in an array to see if someProp matches value and, if so, increments the count on the entry and returns the entry:
function updateAndReturnMatch(array, value) {
array.forEach(function(entry) {
if (entry.someProp == value) {
++entry.count;
return entry;
}
});
}
But calling updateAndReturnMatch gives us undefined, even if the entry was found and updated.
The reason is that the return inside the forEach callback returns from the callback, not from updateAndReturnMatch. Remember, the callback is a function; return in a function returns from that function, not the one containing it.
To return from updateAndReturnMatch, we need to remember the entry and break the loop. Since you can't break a forEach loop, we'll use some instead:
function updateAndReturnMatch(array, value) {
var foundEntry;
array.some(function(entry) {
if (entry.someProp == value) {
foundEntry = entry;
++foundEntry.count;
return true; // <== Breaks out of the `some` loop
}
});
return foundEntry;
}
The return true returns from our some callback, and the return foundEntry returns from updateAndReturnMatch.
Sometimes that's what you want, but often the pattern above can be replaced with Array#find, which is new in ES2015 but can be shimmed for older browsers:
function updateAndReturnMatch(array, value) {
var foundEntry = array.find(function(entry) {
return entry.someProp == value;
});
if (foundEntry) {
++foundEntry.count;
}
return foundEntry;
}
The function e() isn't returning anything; the inner anonymous function is returning its e value but that return value is being ignored by the caller (the caller being function e() (and can the multiple uses of 'e' get any more confusing?))
Because
function(e) {
return e;
}
is a callback. Array.forEach most likely calls it in this fashion:
function forEach(callback) {
for(i;i<length;i++) {
item = arr[i];
callback.call(context, item, i, etc.)
}
}
so the call back is called, but the return doesn't go anywhere. If callback were called like:
return callback.call();
the it would return out of forEach on the first item in the array.
You can use for...of to loop over iterable objects, like array, string, map, set... as per Mozilla docs.
const yourArray = [1, 2, 3]
for (const el of yourArray) { // or yourMap, Set, String etc..
if (el === 2) {
return "something"; // this will break the loop
}
}