Reputation: 93
I am doing an algorithm challenge for practice in JS. I have a program that runs through a loop, and when the condition is met, the function should return false. However, when the condition is met, the return doesn't work and the function always ends up returning true.
const isDiagonalLeftWristband = (band) => {
band.forEach((row, y) => {
row.forEach((item, x) => {
for(let i = 0; (i < band[y].length - x) && (i < band.length - y); i++) {
if (band[y][x] !== band[y+i][x+i]) {
console.log(false) //FALSE GETS OUTPUTTED MULTIPLE TIMES
return false;
}
}
})
})
return true;
}
const band3 = [
["A", "B", "C"],
["C", "Z", "B"],
["B", "C", "A"],
["A", "B", "C"]
];
console.log(isDiagonalLeftWristband(band3))
Output:
false //from console log
false //from console log
true //from function return statement
Any help would be greatly appreciated!
Upvotes: 6
Views: 2638
Reputation: 1036
The return false
will only exit the (item, x) => {}
anonymous function and not the isDiagonalLeftWristband()
as you expect. After the two forEach
are executed isDiagonalLeftWristband()
will always return true
on the end. You can use loops to avoid this problem.
const isDiagonalLeftWristband = (band) => {
for (let [y, row] of band.entries()) {
for (let [x, item] of row.entries()) {
for(let i = 0; (i < band[y].length - x) && (i < band.length - y); i++) {
if (band[y][x] !== band[y+i][x+i]) {
console.log(false) //FALSE GETS OUTPUTTED MULTIPLE TIMES
return false;
}
}
}
}
return true;
}
const band3 = [
["A", "B", "C"],
["C", "Z", "B"],
["B", "C", "A"],
["A", "B", "C"]
];
console.log(isDiagonalLeftWristband(band3))
forEach
is not designed to terminate early. It will always iterate over all the elements. (it's in the name :)). From the MDN documentation:
There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.
Early termination may be accomplished with:
A simple for loop A for...of / for...in loops Array.prototype.every() Array.prototype.some() Array.prototype.find() Array.prototype.findIndex()
Array methods: every(), some(), find(), and findIndex() test the array elements with a predicate returning a truthy value to determine if further iteration is required.
You can instead use one of the suggested functions designed to test the elements of an array with a predicate. every()
tests if all elements of an array pass some test; which is, at least semantically, what you need.
const isDiagonalLeftWristband = (band) => {
return band.every((row, y) => {
return row.every((item, x) => {
for(let i = 0; (i < band[y].length - x) && (i < band.length - y); i++) {
if (band[y][x] !== band[y+i][x+i]) {
return false;
}
}
return true;
});
});
}
const band3 = [
["A", "B", "C"],
["C", "B", "B"],
["B", "C", "A"],
["A", "B", "C"]
];
console.log(isDiagonalLeftWristband(band3))
Upvotes: 3
Reputation: 252
the return false;
statments only return the value to the function it belongs to, which is
(item, x) => {
for(let i = 0; (i < band[y].length - x) && (i < band.length - y); i++) {
if (band[y][x] !== band[y+i][x+i]) {
console.log(false) //FALSE GETS OUTPUTTED MULTIPLE TIMES
return false;
}
}
}
your code must work in a way that it can return the false to the main function, you can use this approach:
const isDiagonalLeftWristband = (band) => {
let returnValue = true;
band.forEach((row, y) => {
row.forEach((item, x) => {
for(let i = 0; (i < band[y].length - x) && (i < band.length - y); i++) {
if (band[y][x] !== band[y+i][x+i]) {
console.log(false) //FALSE GETS OUTPUTTED MULTIPLE TIMES
returnValue = false;
// return false;
}
}
})
})
return returnValue;
}
What domondo suggested is way better because the function exists once it finds the first false
Upvotes: 0