Javascript – creating "some" function - javascript

Trying to create "some" function. i.e., return true if any of the elements in teh array satisfies the condition
function some(array, predicate) {
for (var i = 0; i < array.length; i++) {
if (predicate(array[i]))
return true;
}
return false;
}
console.log(some([NaN, 3, 4], isNaN));
// → true
console.log(some([2, 3, 4], isNaN));
// → false
Question 1: Above is the solution in the book and I'm not sure why "return false" would overwrite "return true" in every case. The above solution seems to suggest that "return false" will be run only if "return true" was never run – WHY??
My solution looked like this.
var some = function(array, condition) {
var answer = false;
for(var i=0; i<array.length; i++) {
if(condition(array[i])) {answer = true};
}
return answer
};
Question 2: Is the book solution better because it takes less memory (ie the "answer" variable)?
Thanks!

return controls where the execution pointer is located for the currently executing script. When return is encountered it moves the execution pointer out of the function, and as a result, the function will stop executing. This means that if return true is executed, return false will not be.

The solution in the book is predicated on the fact that the return keyword used within the body of a for loop will cause the loop to stop execution and return.
Take a look at the at the Interrupt a function section of the return documentation, which states:
The return statement ends function execution and specifies a value to
be returned to the function caller.
In your example, as soon as the condition is matched, the book's solution will no longer continue to iterate through the array and will return (since that's what return does per the definition above).
Let's look at your solution:
var some = function(array, condition) {
var answer = false;
for(var i=0; i<array.length; i++) {
if(condition(array[i])) {answer = true};
}
return answer
};
What happens if the condition is met? You're setting the answer to true, but the loop will continue to check subsequent elements in the array.
Consider the use case where the array is very large and you want to find a specific value within the array.
Which do you think would be more efficient: the one that stops after it finds the match or the one that returns the match only after having looking at all elements?
In this case, the answer is the latter. Don't keep looping through all elements if you've already found what you need.

When the execution hits a return statement, it leaves the current function regardless of which block it was in within that function.
As soon as an array element corresponds to the predicate, it returns true. If the execution exits the for loop normally, it means not a single value was valid, so we can return false.
The book's answer is better, not because it doesn't create an extra variable (that doesn't matter), but because it doesn't check all variables every time. As soon as an array element is valid, it exits the function.

You can use the built in method of Array, some():
var test = [NaN, 3, 4].some(isNaN); // true

What that function does is
function some(array, predicate) { // return a boolean value (true, false)
// as soon an Array key matches `predicate`
for (var i = 0; i < array.length; i++) {
if (predicate(array[i])) return true; // if Array key isNaN exit function as `true`
}
// We're 1. already out of the function or 2. all keys are looped.
// This function needs to return a boolean so exit with `false`
// since all Array keys are Numbers
return false;
}
the above explains it all. Remember the part that says:
"return a boolean value (true, false) as soon an Array key matches predicate"
In your example, you're not exiting the function, so if you passed for example an
array of 1000 keys, every single key would be looped, which the function is not meant to do since it's purpose it to:
Return (exit) as true if at least one key matches the predicate condition
looping all other keys is useless since we already discovered that one key matches.
Yes, var consumes interpreter memory (nothing to worry about).

Related

writing the Array.every() function

I am wondering how you can write the Array.every() function yourself, with a for loop. In my example the for loop will print true 5 times for each iteration. How can I make it return true just once if all values pass, like the Array.every() function?
var array = [1,2,3,4,5];
console.log(array.every(function(num){return num < 6}))
// the for loop will return true 5 times
for(i=0;i<array.length;i++){
if(array[i] < 6)
console.log(true)
}
"In my example the for loop will return true 5 times for each iteration."
No it won't, because the first return statement returns immediately without iterating over the rest of the items. So really what you've implemented is a simple version of the .some() method, which returns true if at least one item matches the condition.
If you just want a simple for loop implementation to test that every item matches the condition, reverse the test logic and return false as soon as you find an element that does not match. And if no items in the loop fail the test then the loop will complete so return true
afterwards:
for(i=0;i<array.length;i++){
if(!(array[i] < 6))
return false;
}
return true;
You may like to take a look at a full implementation of .every(): MDN's .every() polyfill

How does this "if" without operators work?

I am relatively new to Javascript and am working through ch. 5 of Eloquent Javascript. I came across some code that I don't quite understand. I know HOW it works (the general method and steps), but I don't understand WHY it works.
The code is here:
function filter(array, test) {
var passed = [];
for (var i = 0; i < array.length; i++) {
if (test(array[i]))
passed.push(array[i]);
}
return passed;
}
Basically the function takes the element the 'for loop is iterating over' from the array, and compares it to the test parameter.
I am wondering how/why this works:
if (test(array[i]))
There is no || && or other 'comparison operators'. How does it compare values with only using parenthesis?
How is test compared to the array[i] value with no operators?
Link to file: http://eloquentjavascript.net/05_higher_order.html
go to 'Filtering an Array' exercise
Thanks!
Whatever is inside the parentheses of an if statement will be evaluated. If the result is falsy (false, 0, "", NaN, null, undefined) it fails and if the result is truthy (everything else) it passes. So if your if statement contains a function call if (test(something)) {}, then the if statement just says if the result of the function call is truthy then pass.
Also, && and || are not comparison operators, they are boolean operators. They just connect the result of two statements, like true || false which evaluates to true.
I am not quite sure, but I think this is a custom function. Most likely there is some comparison there and the result of the function is True/False. If you give us the whole code we could explain it better to you.
This code is accepting a test parameter that is what is called a "predicate function" i.e. a function that given an element will return true or false.
It's going to be used for example with
var big_numbers = filter(numbers, function(x){ return x > 100; });
i.e. the expected parameter test is actually code.
In Javascript passing code is very common and idiomatic. It's something that is more annoying in other languages that don't support the concept of "closure" and of "nested function", forcing all code to live at the top level, being given a name and to have no context (e.g. the C language).
'test' here is a function, not a value. In Javascript, each function is an object and can be passed as parameter. In this case, test is a function that take one parameter and return true or false base on the parameter value.
So in the for loop, test function is called with each array element and if the result is true, it will be store in another array. Eventually, passed elements would be return to the function caller.

javascript function won't loop

Here is a piece of a javascript practice problem that I am working on:
function combo(str){
var splitStr=str.split("");
for (var i=0; i<splitStr.length; i++){
return splitStr[i];
}
}
console.log(combo("dog"));
Why won't the loop return all three letters? It prints "d" and stops. If I take the loop out of the function, it works.
What am I doing wrong? Please explain.
return ends the invocation of the function, giving you back whatever is after that return
Your code structure looks like you wanted it to act like yield but ES5- does not support this so you can't use it (yet), and you would still have other problems (i.e. you'd be logging just the first generated result)
Instead, pass your console.log (bound to console) into a the loop;
function combo(str, callback){
var splitStr=str.split("");
for (var i=0; i<splitStr.length; i++){
callback(splitStr[i]);
}
}
combo('dog', console.log.bind(console));
With return you will end the function and come out of it with that data, next things wont be called
You can return an array instead like this.
function combo(str){
return splitStr=str.split("");
}
console.log(combo("dog"));
You are returning from inside the for loop and this ceases the function's execution. If you want to return each letter of the array, just return the split array itself:
function combo(str) {
return str.split("");
}
The behavior you seem to want is somehow achievable using generator function (function*).
function* combo(){
var splitStr = str.split("");
for (var i=0; i < splitStr.length; i++){
yield splitStr[i];
}
}
Then you'd invoke it like this:
var generator = combo("dog");
console.log(generator.next()) //d
console.log(generator.next()) //o
console.log(generator.next()) //g
Please note, however, that so far only few browser support this feature.
return stops the execution of the function. The rest of the loop is not happening.
'return' within the loop ends the loop and returns the first value, since it allowed the loop to run only once.
putting the 'return' statement outside of the scope {} of the loop will allow the loop to continue to run/repeat.

Does the ForEach loop allow using break and continue?

Does the ForEach loop allow us to use break and continue?
I've tried using both but I received an error:
Illegal break/continue statement
If it does allow, how do I use them?
No, it doesn't, because you pass a callback as a return, which is executed as an ordinary function.
Let me be clear:
var arr = [1,2,3];
arr.forEach(function(i) {
console.log(i);
});
// is like
var cb = function(i) {
console.log(i);
// would "break" here do anything?
// would "continue" here do anything?
// of course not.
}
for(var j = 0; j < arr.length; j++) {
cb(arr[j]);
}
All forEach does is call a real, actual function you give to it repeatedly, ignore how it exits, then calls it again on the next element.
In that callback function if you return it will incidentally work like continue in the case of forEach. Because the rest of the function won't execute that time, and it will be called again. There is no analogue of break.
Ruby supports this flexibility, using blocks/procs instead of methods/lambdas.
Per Mozilla's documentation:
Note : There is no way to stop or break a forEach loop. The solution is to use Array.every or Array.some. See example below.
every and some are exactly like forEach, except they pay attention to the return value of the callback. every will break on a falsey value and some will break on a truthy value, since they shortcircuit. They are exactly analogous to && and ||. && tests whether every expression is truthy, || tests for whether some is, which should help you remember how short-circuiting works with every and some. When in doubt, try it.
As already answered, you cannot use continue or break inside a JavaScript Array.prototype.forEach loop. However, there are other options:
Option 1
Use the jQuery .each() function (Reference).
Simply return true to continue, or return false to break the loop.
Option 2
Just use return to continue or throw new Error() to break. I don't necessarily recommend doing it this way, but it's interesting to know that this is possible.
try {
[1, 2, 3, 4].forEach(function(i) {
if (i === 2) {
return; // continue
}
if (i === 3) {
throw new Error(); // break
}
console.log(i);
});
}
catch (e) {
}
The expected result is just 1

Mysterious working of a Javascript - forth value returns no exception when array defined for three

The below code works fine in javascript
var items = [1,2,5]
for (var i = 0, item; item = items[i]; i++) {
console.log(item = items[i]);
}
OUTPUT : 1 2 5
I am not sure how this program works successfully
The forth item is undefined and what will happen in the last iteration.
Can we able to create a similar function in Java ?
items[3] at the end how it will be handled in the above function?
Two key things to start with:
First, in JavaScript, whenever you try to retrieve the value of an object property that doesn't exist (including an array entry), the result of the retrieval is the value undefined.
Second, when you use a value like a flag, as in an if statement or the "test" part of a for (or any other loop), etc., JavaScript with "coerce" whatever value you used to be boolean. [This is different from (say) Java, which requires that you only use boolean variables as that sort of flag.] Because JavaScript does this and it comes up a lot, we use the terms "truthy" (coerces to true) and "falsey" (coerces to false) to categorize values. The "falsey" values are 0, "", NaN, null, undefined, and of course false; all other values are truthy.
Okay, armed with that information, let's look at your loop:
The forth item is undefined and what will happen in the last iteration.
There are only three iterations. A for statement is made up of three expressions separated with ;, and a loop body. The expressions are the initialization, the test, and the increment:
// /--------------------------------initialization
// | /--------------- test
// | | /--- increment
// vvvvvvvvvvvvvvv vvvvvvvvvvvvvvv vvv
for (var i = 0, item; item = items[i]; i++) {
The loop is evaluated like this:
Do the initialization
Do the test
If the test was false, terminate
Do the body
Do the increment
Go back to step 2
The "test" part of your for loop is item = items[i], which is an assignment. The value of an assignment expression is the value being assigned. So when i is 3, that assignment is item = items[3] which is effectively item = undefined. That assignment has the value undefined, which is a falsey value, so the body of the loop isn't run a fourth time.
Can we able to create a similar function in Java ?
Yes, it looks almost identical other than that with Java, you use a type with the variables, and you can't use (just) the item = items[i] thing for the "test" part of the for (for the same reason you get an exception below).
items[3] at the end how it will be handled in the above function?
You don't have any function in your question. After the loop, in JavaScript, accessing items[3] would give you undefined (see above). In Java, it result in an ArrayIndexOutOfBoundsException.
Side note: The = in this line is an assignment, not a comparison:
console.log(item = items[i]);
If you meant to compare them, do this:
console.log(item == items[i]);
...which will give you the output
true
true
true
Here is what happens in your loop:
1. i = 0; item = 1; i = 1;
2. item = 2; i = 2;
3. item = 5; i = 3;
4. item = undefined; --> breaks the loop
Notice, that if you'd have items = [0,1,2], your loop would never be executed.
The code works fine as you have assignment in the for loop condition check
During the first iteration item is undefined but it executes the loop without termination as you assign the first value of array to item and it is no more undefined
Try it with comparision operator as item == items[i], you will find your loop no more executes even once.
When it comes outside of array i.e. items[3] which returns undefined and thus temp goes undefined and terminates the loop as in javascript undefined, null, 0 and false all are same.
This function wont work in Java as it would complain that it requires condition not the assignment in for loop.

Categories