Why is Javascript 'every' function returning false? - javascript

I have a quick question on why my function is returning false, when I expect it to be returning true. I have looked at the documentation for Array.prototype.every, and I still can't seem to find it. Thanks for your help in advance.
For some context, this is part of a coderbyte question called arithGeo. The current function I am working on here is supposed to return true if the difference between each element is the same. Here, I expect this to return true, since each element is 5 apart from the next.
Here is my function
var arr = [5, 10, 15];
function isArith(arr){
var diff = arr[1] - arr[0];
return arr.every(function(val, ind, col){
// if statement checks to make sure I stay in bounds.
if(col[ind + 1] !== undefined){
var next = col[ind + 1] - val;
console.log(diff === next );
// logging shows the following statement to be true, for every iteration
return diff === next;
}
});
}
var arith = isArith(arr);
console.log('arith: ', arith) // logs false

On the last iteration you'll return undefined, which will be interpreted as false. The code does that because if the if fails (which it does on the last element) there's no return statement. If you add return true to the end after the if it should work.

When you reach the last element, you test to see if there is a next element so you don't compare the last element with nothing. That's great. But in that case, you forget to return anything, and the default return is undefined, which is falsy. Just put in else return true.

Related

Why is else if block ignored when I add else block?

Why this happens? I'm doing exercise on FreeCodeCamp (Return the lowest index at which a value (second argument) should be inserted into an array (first argument) once it has been sorted. The returned value should be a number.)
I know there are better ways to do this but I'm interested in this problem.
This is my code:
function getIndexToIns(arr, num) {
let pos = 0;
arr.sort((a, b) => a - b);
console.log(arr);
for(let arrs in arr) {
if (num == arr[+arrs]) {
return pos = +arrs;
}
else if (num < arr[+arrs]) {
pos = ((+arrs));
return pos;
}
else {
return "why"
}
}
return 0;
}
console.log(getIndexToIns([2, 20, 10], 19));
console.log(getIndexToIns([2, 5, 10], 15));
The problem is you are returning "why" at the start of the loop, so basically 19 would be compared to 2, and when it finds that 19 === 2 is false and 19 < 2 is false, it returns "why" and gets out of the function without looping through the elements, same goes for the second array.
Try to use an array in which all the values are bigger than num and you will see that it gives you 0.
the solution would be to erase the third else altogether.
Hope this helped you.
The problem is in your if-else-if flow. The if-else-if work procedure is like below:
if is false, check next else if condition
if next else if condition is also false, will check the next else if condition if ther is any.
if there is no more else if condition, it will find else condition and work on that, if not found, will work on rest of statements
So, in your case, if first if is true, the look works only once, if that is false, then check next else if and if it is true, the loop ends, otherwise directly goes to else condition and returns from here running the loop only once. That's why it runs only once.

Difficulty with Boolean and arrays in Javascript

Here, I am trying to write a code that takes a list of integers as a parameter and searches for the value 7. The function will return a boolean value representing true if 7 is in the list and false if it is not. This is what I have tried so far:
Could it be something with my else statement? Do I end it too soon? Or not soon enough?
You can simply use an array and use includes as per ECMA2016 like below:
if([2,5,7].includes(value)) {
return true;
}
return false;
or with list
var flag = false;
for(var i=0; i<arguments.length; i++)
{ if(arguments[i] == this) { flag = true; break; }}
return flag;
Javascript already has a function to do this. Array.prototype.includes(). You use it like this:
const containsSeven = list.includes(7)
If you are looking for something more complicated, like whether an item is an object and contains a particular key value pair for example, you can use Array.prototype.some()
Your declaration of the if statement is wrong. The else tag is on the wrong line. If you use else, it should come after the if-block.
But moving the else-block up, won't fix your function, because it will only return true if the first element in your array is a 7.
There are many good ways to do it, such as using higher order functions, but as it seems you are new to the language.
EDIT: Therefore, I would suggest one of the two simple ways below:
1) You could store the number of 7s found in the array in a for loop. Afterwards return false if the number of 7s is 0 or true if it the number is higher than 0
2) Another, much quicker way would be to return true in the for-loop when you encounter a 7 and after the for-loop just return false. Because a return statement exits the scope - which is your function - not only the for-loop would come to an end but also your function would return true much earlier.
For the second option, your function would look like this:
function find_value(list) {
for (let i = 0; i < list.length; i++) {
if(list[i] == 7) {
return true
}
}
return false
}
You can coerces to boolean the result of Array.prototype.find() which returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
Code:
const list1 = [4, 5, 6, 7, 8];
const list2 = [1, 2, 3, 4, 5];
const findTheNumber = (arr, num) => !!arr.find(n => n === num);
console.log(findTheNumber(list1, 7));
console.log(findTheNumber(list2, 7));
Try this way
function search(list , value){ // Value = 7;
return true ? list.indexOf(value) > -1 : false
}

How to avoid short-circuited evaluation in JavaScript?

I need to execute both sides of an && statement, but this won't happen if the first part returns false. Example:
function doSomething(x) {
console.log(x);
}
function checkSomething(x) {
var not1 = x !== 1;
if (not1) doSomething(x);
return not1;
}
function checkAll() {
return checkSomething(1)
&& checkSomething(3)
&& checkSomething(6)
}
var allValid = checkAll(); // Logs nothing, returns false
The problem here is that doSomething(x) should log 3 and 6, but because checkSomething(1) returns false, the other checks won't be called. What is the easiest way to run all the checks and return the result?
I know I could save all the values in variables and check those subsequently, but that does not look very clean when I have a lot of checks. I am looking for alternatives.
Use a single &. That is a bitwise operator. It will execute all conditions and then return a bitwise sum of the results.
function checkAll() {
return checkSomething(1)
& checkSomething(2)
& checkSomething(3)
}
You can multiply the comparison result and cast it to boolean.
function checkSomething(x) {
var not1 = x !== 1;
if (not1) alert(x);
return not1;
}
function checkAll() {
return !!(checkSomething(1) * checkSomething(2) * checkSomething(3));
}
document.write(checkAll());
Or take some array method:
function checkAll() {
return [checkSomething(2), checkSomething(2), checkSomething(3)].every(Boolean);
}
Coming back to my own question 2,5 years later I can agree with the people in the comments on how bad this code is by being based on side effects and therefore violating the single responsibility principle.
I just want to provide a proper solution for people visiting this page with the same question.
function doSomething(x) {
console.log(x);
}
function checkSomething(x) {
return x !== 1;
}
var values = [1, 3, 6];
var validValues = values.filter(checkSomething); // -> [3, 6]
validValues.forEach(doSomething); // -> Logs 3 and 6
var allValid = validValues.length === values.length; // false
As you can see, the checkSomething function now only does one thing: check something. The doSomething logic runs separately after all the checks are done.
A function should always either do something or return something, not both. Of course there are exceptions to this, but it is a good rule of thumb. This makes the code more predictable, testable and understandable.
Now, if at some point I want to check if all values are valid without "doing something", I can actually do this...
var allValid = checkSomething(1) && checkSomething(3) && checkSomething(6);
...without having to worry about side effects.
Conclusion: You don't want to avoid short circuited evaluation

Javascript while loop with function as conditional

My understanding is that the contents of a while loop executes while the condition is true. While working off of an example from an awesome O'Riely book, I've come across this implementation of the while loop...
window.onload = function(){
var next, previous, rewind; // globals
(function(){
// Set private variables
var index = -1;
var data = ['eeny', 'meeny', 'miney', 'moe'];
var count = data.length;
next = function(){
if (index < count) {
index ++;
};
return data[index];
};
previous = function(){
if (index <= count){
index --;
}
return data[index];
};
rewind = function(){
index = -1;
};
})();
// console.log results of while loop calling next()...
var a;
rewind();
while(a = next()){
// do something here
console.log(a);
}
}
I guess I'm wondering why, in this code, the while loop is not resolving to true infinitely? The function, next() isn't returning false after var index stops incrementing (++), is it? Shouldn't the console just be outputting eeny, meeny, miney, moe, moe, moe, moe.....etc...
I know this has probably been asked in some form, but have done searching and can't find a question or answer that explains using while (a = function()) {// do something} and how this loop is stopping after one pass through the array.
About why while (a = next()) {/*do something*/} doesn't repeat infinitely, it's about being coerced to false that counts - arguments are converted to booleans before being tested by the while loop. Things that coerce to false include 0, -0, undefined, null, "", NaN, and of course false itself.
When you assign something, it returns the value of the assignment itself. For example, if you do something like this:
var a;
console.log(a = '1234567890abcdefghijklmnopqrstuvwxyz');
It will log 1234567890abcdefghijklmnopqrstuvwxyz.
When the next performs index++, this increments the counter for the element index in the data array. This means that it will look for the next element in the data array every time you run the next() function - if there are no more elements, it will return undefined and therefore end the loop.
For example, see this:
var index = 0;
data = ['a','b','c'];
data[index]; // 'a'
index++;
data[index]; // 'b'
index++;
data[index]; // 'c'
index++;
data[index]; // undefined - if passed this will coerce to false and end the loop
Boolean(data[index]); // false
if (index < count) {
index ++;
};
When index is count - 1, this will still change index to count, right? And count is data.length. So, it then does this:
return data[index];
Which becomes
return data[data.length];
Since the length of an array is out of bounds of the array (they are zero-based), it will give undefined.
while(a = next()){
will become
while(a = undefined){
Since undefined is a falsy value, the loop will not be entered.
No,
It is not going to be an infinite loop. The while loop is basically going through the array and outputting it and when it is at the end of the array it just returns false and quits the loop.
This is something like;
foreach(a as nextArray)
{
//output
}
Hope this helps.

Implementing `continue;` keywords in jQuery's `each();` method

Imagine that I want to loop over a list of jQuery objects, and for each of them execute some functions. However, if in some place, a criteria is not met, then I simply want to continue; to other objects. The simple pseudo-code might be something like:
$('#element').each(function(){
// some code here
if (!$(this).is('.included')) {
continue; // This keyword of course, doesn't work here
}
// more code here, which won't get executed for some elements
});
I wan to achieve the same effect as:
for (var i = 0; i < 10; i++) {
if (i % 2 == 0 ) {
continue;
}
console.log(i);
}
I know that I can return false; somewhere inside each(); method, to completely break the looping. But I don't want to break looping. I only want to skip some elements. I also know that I can use if-else blocks to skip elements, but is there a more neat way to do this?
simply use return; instead of continue; (not return false;).
When you use the .each jQuery function, you're passing a function to be executed for each value in the Array. The continue keyword is not implied in functions, but only in a direct loop. The reason jQuery breaks when you return a false value is because of this line in the jQuery libary:
if ( callback.apply( object[ name ], args ) === false ) {
break;
}
jQuery purposely exits the loop when the executed function returns false. It would be common sense to add this, right? Since it uses === you can return anything that isn't directly equal to false, including undefined, null, 0, true, or anything. As long as it doesn't equal false, the loop will continue.
$.each([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], function(i) {
if(i > 5) { return false; } // if(i > 5) { break; }
if(i < 2) { return null; } // if(i < 2) { continue; }
console.log(i);
});
Your console would look like this:
2
3
4
5
Notice it didn't log 0 and 1. i was less than 2, so it continued without logging. Notice it didn't log 6, 7, 8, and 9. This is because when i became more than 5, it returned false.
The jQuery.each docs says:
" Returning non-false is the same as a
continue statement in a for loop; it will skip immediately to the next
iteration. "
I usually do return 'continue'; which is both readable and more self-explanatory than simple return;, return true; or return 1;
I've also encountered return 'non-false'; which is quite funny in a geeky way.
I don't really see the need for the continue statement:
$('#element').each(function(){
// some code here
if( $(this).is('.included') ) {
// more code here, which won't get executed for some elements
}
});
This ought to do exactly the same, unless I'm missing something.

Categories

Resources