So I am supposed to create a function that has two inputs: an array of Boolean functions and a value to run through each of those functions. I am supposed to return a Boolean value indicating whether or not all of the functions return true. If at least one of the functions returns false then reduce should return false.
The issue I am having is that even if one of the functions evaluates to false and the accumulator is set to false if there is another function in the array after it which results in a true value then it just returns true even though the preceding function was false.
I did some reading and apparently, there isn't really a way to break out of a running reduce method.
const allClear = (funcArr, value) => {
// iterate through funcArr using reduce
return funcArr.reduce((acc, fn) => {
if (fn(value) === false) {
return false;
} else {
return true;
}
}, false)
}
and here are the test cases that make up the array of functions as well as two calls to the function...
const isOdd = num => num % 2 === 1;
const isPositive = num => num > 0;
const multipleOfFive = num => num % 5 === 0;
const numFnArr = [isOdd, isPositive, multipleOfFive];
console.log(allClear(numFnArr, 25)) // should log true
console.log(allClear(numFnArr, -25)) // should log false
I have tried quite a few variations of my function but to no avail. As soon as I set the accumulator to false, it will be set back to true by the next function in the array (speaking of the second function call with -25) and cannot figure out how to break out of reduce and return false once I find a false result from running through the functions!
Thank you for any tips or help!
CodePudding user response:
The callback function should check the accumulator. If it's false
, it should just return false
without bothering to call the next function, since that means at least one of the earlier functions returned false
.
This also means that the initial value of the accumulator should be true
, otherwise you'll stop immediately.
In addition, you can use !!
to convert the value of the fn(value)
call to a boolean.
const allClear = (funcArr, value) => {
// iterate through funcArr using reduce
return funcArr.reduce((acc, fn) => {
if (!acc) {
return false;
}
return !!fn(value);
}, true)
}
const isOdd = num => num % 2 === 1;
const isPositive = num => num > 0;
const multipleOfFive = num => num % 5 === 0;
const numFnArr = [isOdd, isPositive, multipleOfFive];
console.log(allClear(numFnArr, 25)) // should log true
console.log(allClear(numFnArr, -25)) // should log false
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You could take Array#every
.
const allClear = (funcArr, value) => funcArr.every(fn => fn(value));
const isOdd = num => num % 2 === 1;
const isPositive = num => num > 0;
const multipleOfFive = num => num % 5 === 0;
const numFnArr = [isOdd, isPositive, multipleOfFive];
console.log(allClear(numFnArr, 25)) // should log true
console.log(allClear(numFnArr, -25)) // should log false
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
With Array#reduce
and logical AND &&
const allClear = (funcArr, value) => funcArr
.reduce((r, fn) => r && fn(value), true);
const isOdd = num => num % 2 === 1;
const isPositive = num => num > 0;
const multipleOfFive = num => num % 5 === 0;
const numFnArr = [isOdd, isPositive, multipleOfFive];
console.log(allClear(numFnArr, 25)) // should log true
console.log(allClear(numFnArr, -25)) // should log false
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>