If statement not working inside foreach loop javascript - javascript

I am trying to return the first value which is greater than 25 from an array, without using other methods such as filter. Assume the array is always sorted.
The function always returns undefined. Why is that happening? Here is the code:
function checkArr(arr){
arr.forEach(i => {
if (i>25) return i;
})
}
console.log(checkArr([10,20,34,45]))
The output should be 34.

When you use forEach, you execute another function for every item in the array. That function can return a value just fine, but it'll get completely ignored. If you want to return a value in the checkArr function, you have to do something like this:
function checkArr(arr) {
for (let i of arr) {
if (i>25) return i;
}
}

You can use find function instead of forEach. And you must return a result of this function to get an answer instead of undefined.
function checkArr(arr) {
return arr.find(i => i > 25);
}
console.log(checkArr([10,20,34,45]))
forEach function returns nothing, it just makes some actions for each element in an array.

Your function is not returning anything. And returning inside a forEach won't have any effect, since forEach always returns undefined. You can use a simple while loop to do this:
function checkArr(arr){
var i = 0;
while (i<arr.length) {
if (arr[i]>25) return arr[i];
i++;
}
return null; // if no entry is greater than 25
}
console.log(checkArr([10,20,34,45]));

The forEach() method executes a provided function once for each array element.
From the above statement it is clear that you can not return from the middle of the execution of the loop.
Use for...of loop instead to return as soon as the condition is true:
function checkArr(arr){
for(var item of arr){
if (item > 25) return item;
}
}
console.log(checkArr([10,20,34,45]))

Seems like you're looking for find:
function checkArr(arr) {
return arr.find(i => i>25);
}
console.log(checkArr([10,20,34,45]));

It's because you're passing a delegate function when calling .forEach.
The return of the delegate is getting lost and isn't applying to anything. To get your desired result, you'll want to exit the calling function checkArr.
This can be done using a simple for loop.
function checkArr(arr){
for (var i = 0; i < arr.length++; i++) {
if (arr[i] > 25) return arr[i];
}
}
console.log(checkArr([10,20,34,45]))
This approach also supports older browsers, unlike some, every and forEach

"Good code is short, simple, and symmetrical - the challenge is figuring out how to get there".
function checkArr(arr){
return arr.filter(m => m > 25)
}
checkArr([10,20,34,45]);

Related

How to create a function that acts the same way as the method includes()

I am trying to create a function that would work the same way as the method includes by using two parameters. Right now it only works with methods that would return false, however, true doesn't work and I can't figure out why it doesn't go into the if statement.
function includes(array, value) {
for(let i =0; i < array.length; i += 1) {
if (array[i] === value) {
return true;
} else {
return false;
}
}
}
includes([1,2,3,4,5], 3);
You're returning a result on the very first iteration of the loop, thereby terminating the function before you've checked every element.
You can easily fix this by only returning true if you do find it, and otherwise just continuing the loop, returning false only after the loop if it wasn't found:
function includes(array, value) {
for(let i =0; i < array.length; i += 1) {
if (array[i] === value) {
return true;
}
}
return false;
}
You can use indexOf method from Javascript and do like this:
function includes(array, value) {
return array.indexOf(value) !== -1
}
console.log(includes([1,2,3,4,5], 3));
This is a short and simple solution that also supports IE9 whereas Javascript's includes method doesn't in any IE as per MDN Docs.
Why don't you use includes method in the includes function?
function includes(array, value) {
return array.includes(value)
}
But I don't see what is the point of having a function like that.
If you need a function that will mimic includes method:
function includes(array, value) {
for(e of array) {
if (e == value) return true;
}
return false;
}
Instead of for-of loop, you can use other array methods like find, indexOf, filter, but using for loop is better idea in terms of performance because you can break early. It can be important when you work on huge data.

forEach vs for loop?? for loop seems to work, but not with forEach. Why? Please can someone explain?

/*please have a look at the following function. Its a simple function. I want to iterate over the movies array and return the element; only if the element's title is exactly same as the argument passed in. otherwise return false at the end of the iteration.
The problem is, it always return false. However, if I use a regular forloop instead of forEach loop, it works perfectly fine.. can someone please explain why is this situation?????? Thank You in advance.
*/
function searchMovies(title) {
movies.forEach(function(ele){
if(ele.title === title){
return ele;
}
});
return false;
}
//movies array
var movies = [
{title: 'The Hobbit'},
{title: 'The Great Gatsby'},
{title: 'Gone with the Wind'}
];
//the following line calls the function
searchMovies('The Great Gatsby');
You're returning from inside the callback passed to forEach which forEach ignores every time and call the callback to the next element. What you need is to use find like this:
function searchMovies(title) {
var found = movies.find(function(ele){
return ele.title === title;
});
return found; // found will be either and item from the array (if find found something) or undefined (if it doesn't)
}
Note 1: the movies array should be either defined before the function searchMovies, or passed to it as a parameter (the best approach).
Note 2: if you want to return an array of all the matched element (if there is duplicates in the array and you want to return all of them), then use filter, which is used the same way and it return an array of all the matched elements (an empty one if nothing matched).
Because you're returning inside the forEach function.
function searchMovies(title) {
var foundMovie = false;
movies.forEach(function(ele) {
if (ele.title === title) {
foundMovie = ele;
}
});
return foundMovie;
}

Confused about the `return` statement in javascript. Explanation needed

I posted a question not too long ago this morning regarding a kata that I was trying to solve. In that question, (found here if interested Kata Question) I needed to add a return statement to my function so that I would avoid the following error Value is not what was expected.
Now I have my second iteration of my kata solution to try out and here it is:
function isMerge(s, part1, part2) {
var pointer = 0
splitString = s.split('');
splitString.forEach(function(character) {
if (part1.includes(character) || part2.includes(character)) {
pointer++;
return true;
} else {
return false;
}
});
}
isMerge('codewars','cdw','oears')
I am still getting Value is not what was expected errors when I try to execute the code and this time I'm confused as to why in particular this happens.
For starters, taken from the MDN guide
The return statement ends function execution and specifies a value to be returned to the function caller.
expression
The expression to return. If omitted, undefined is returned instead.
Look at my if/else logic I am specifying a return true and return false condition in my forEach loop to see if all the chars from part1 and part2 are in the string. I am returning something so why is it that I have a Value is not what was expected?.
Second of all, by definition of the return statement, the function is supposed to stop when it reaches that keyword. However, when I place a console.log(character) in the logic, I can see on my console that all of the characters are being outputted so the function is not breaking at all when return true is executed. Why is that?
Third, I am confused as to when to use the return keyword in general. Consider these examples from the MDN docs for ForEach.
Example 1:
function logArrayElements(element, index, array) {
console.log('a[' + index + '] = ' + element);
}
// Notice that index 2 is skipped since there is no item at
// that position in the array.
[2, 5, , 9].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[3] = 9
Example 2:
function Counter() {
this.sum = 0;
this.count = 0;
}
Counter.prototype.add = function(array) {
array.forEach(function(entry) {
this.sum += entry;
++this.count;
}, this);
// ^---- Note
};
var obj = new Counter();
obj.add([2, 5, 9]);
obj.count
// 3
obj.sum
// 16
Not a single return statement to in these examples.
Now look at this .every example.
function isBigEnough(element, index, array) {
return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough);
And finally, from my previous question, I need to add a second return statement like this to avoid the value error.
function isBigEnough(element, index, array) {
return element >= 10;
}
function whenToUseReturn(array) {
return array.every(isBigEnough);
}
whenToUseReturn([12, 5, 8, 130, 44]);
So....... in conclusion, for my original function that started this how am I supposed to exit the loop when I reach false and return it and likewise when all the characters are in the string, how do I return a 'cumulative' true and avoid a Value error. I hope this makes sense and I can clarify with edits to better illustrate my point.
I am returning something so why is it that I have a Value is not what was expected?.
The return statement returns from the callback you pass to forEach, not from isMerge. return statements don't cross function boundaries. isMerge doesn't contain a return statement, hence it returns undefined. If we rewrite the function slightly it might become clearer:
function doSomething(part1, part2) {
return function(character) {
if (part1.includes(character) || part2.includes(character)) {
return true;
} else {
return false;
}
}
}
function isMerge(s, part1, part2) {
splitString = s.split('');
splitString.forEach(doSomething(part1, part2));
}
isMerge('codewars','cdw','oears')
This is equivalent to your code. As you can see, there is no return statement in isMerge.
Not a single return statement to in these examples.
There are no return statements in the forEach examples because forEach doesn't do anything with the return value of the callback, so there is no point in returning anything.
forEach is just a different way to iterate over an array, but it doesn't produce a value like reduce or every.
how am I supposed to exit the loop when I reach false and return it and likewise when all the characters are in the string, how do I return a 'cumulative' true and avoid a Value error.
You cannot exit a forEach "loop". If you have to stop the iteration early, you need to use a normal for (for/in, for/of) loop.
To return and produce a value, you can use your original solution that uses every.
My friend, since you decided to go the "callback way" using .each and the like, you should consider using callbacks, since you cannot return anything in this case. If you do not wish to go the callback way, just use standard javascript, such as:
splitString.forEach(function(character) {
Replace with
for(var i = 0 ; i < splitString.length; i++){
And now you can return. Using "each" to loop an array is just plain unnecessary and prevents you to return.

Self Invoking Function returns "undefined"

Im trying to get a sum of array injected into a function that loops until all the values are added, the console.log right before the "return" logs the right value, meaning the code works, but when I try to use that function with any array it returns "undefined"...
var total = function(arr) {
console.log(arr);
if(arr.length > 1) {
var temp = []
for(var i=0, len=arr.length-1; i<len; i++) {
temp.push(arr[i] + arr[i+1]);
}
total(temp);
}
else {
console.log(arr.join()); // 48, exectly what I need
return parseInt(arr.join());
}
}
var sup = total([1,2,3,4,5]); // undefined
Not completely sure how to debug it..
If your arr.length is greater than one, you will invoke total with the temporary array, however, you don't do anything with this temporary array - you don't return it, or utilize it in any way, so the intermediate results are lost.
In addition - this is not a self invoking function; it is recursion.

How to return from a $.each operation? (jQuery)

Example:
var t = $.each(templos_cache, function(f,g){
$.each(g.requer, function(h,j){
if (parseFloat(g.id) == id){
alert(j.nome); // OK, return 'afrodite'.
return j.nome; // wrong, return [Object object].
}
});
return '';
});
Looking at the code we can see the problem... i can do a set in a variable out of scope but i think that can exist some more elegant way to do this.
To break out of $.each(), simply return false; from the callback function. As quoted from the jQuery documentation:
We can break the $.each() loop at a
particular iteration by making the
callback function return false.
Returning non-false is the same as a
continue statement in a for loop; it
will skip immediately to the next
iteration.
Edit:
Upon realising you may want to return a value, you could simply pass an object to the callback function as this is passed by reference. See How to append a string value during assignment in Javascript? - this isn't at all any more elegant though, so I'd stick with just setting a variable outside of $.each as colinmarc said.
Off the top of my head, setting a variable seems like the most elegant way to do it, like you mentioned:
var foo = '';
$.each(some_list, function(i, e){
...
if(something) foo = 'stuff';
});
in THEORY something like this should do what you want. it should loop through templos_cache, and inside loop through g.requer until id matches g.id. in that case it will set returnValue, and break out of the inside $.each loop. and in the outside loop it checks if returnValue has been set, if so, breaks out of the loop.
I haven't actually tested this. but it seems solid
var returnValue = '';
$.each(templos_cache, function(f,g){
$.each(g.requer, function(h,j){
if (parseFloat(g.id) == id){
returnValue = j.nome;
return false;
}
});
if(returnValue != ''){
return false;
}
});
var t = returnValue;
You may be looking for $.map instead:
var x = [1, 2, 3, 4, 5];
var y = $(x).map(function(i, n){
return n < 4 ? n+1 : undefined;
});
// y == [2, 3, 4]
If you only return one value, y will be [val] and you can always access it with y[0]

Categories