You can use a Generator function to make this task easier.
You can give it an array that contains sub-arrays and then let it walk each of the sub arrays grabbing the item at the same index from each and then OR-ing them. Here is an overview of how this would work:
start:
iteration 1:
mainArray = [ [a01, a02, ..., aNN], [b01, b02, ..., bNN], [c01, c02, ..., cNN] ]
^^^ ^^^ ^^^
pointer | | |
OR together: a01 || b01 || c01 --> result01
iteration 2:
mainArray = [ [a01, a02, ..., aNN], [b01, b02, ..., bNN], [c01, c02, ..., cNN] ]
^^^ ^^^ ^^^
pointer | | |
OR together: a02 || b02 || c02 --> result02
...
iteration NN:
mainArray = [ [a01, a02, ..., aNN], [b01, b02, ..., bNN], [c01, c02, ..., cNN] ]
^^^ ^^^ ^^^
pointer | | |
OR together: aNN || bNN || cNN --> resultNN
end
You can then use Array.from to run through the entire algorithm and get an array from each iteration, so you'd get [result01, result02, ..., resultNN] from the above.
Here is an implementation:
function* sequentialOR(mainArray) {
//convert from arrays to iterators over the arrays
const iterators = mainArray.map(subArray => subArray[Symbol.iterator]());
//call .next() on each iterator to grab the values
let allResults = iterators.map(it => it.next());
//continue until the first is done.
//Since all sub-arrays have the same length this will be the same for all
while(allResults[0].done === false) {
yield allResults
.map(({value}) => value) //get the boolean value
.some(Boolean); //(essentially) run an OR operation
allResults = iterators.map(it => it.next());
}
}
/*
arrBefore = [[true],[false],[true],[false]];
arrAfter = [true];
*/
const input1 = [[true],[false],[true],[false]];
test(input1);
/*
arrBefore = [[true, false],[false, false], [false, true], [false, false], [true, true]];
arrAfter = [true, true];
*/
const input2 = [[true, false],[false, false], [false, true], [false, false], [true, true]];
test(input2);
/*
arrBefore = [[true, false, false, false], [true, true, false, false]];
arrAfter = [true, true, false, false];
*/
const input3 = [[true, false, false, false], [true, true, false, false]];
test(input3);
/*
arrBefore = [[true, true, false, false, false], [false, false, false, false, true]];
arrAfter = [true, true, false, false, true];
*/
const input4 = [[true, true, false, false, false], [false, false, false, false, true]];
test(input4);
//a quick function to print the output
function test(input){
const output = Array.from(sequentialOR(input));
console.log(
`Input: ${JSON.stringify(input)}
Output: ${JSON.stringify(output)}`
);
}
I've chosen to use Array#some here as it's a slightly more expressive way to implement OR. You can easily use Array#reduce to achieve the same effect but since reduce is more generic, it is slightly harder to understand that the operation is OR at a glance:
arrayOfBooleans.reduce((a, b) => a || b, false)
The initial value is set to false as this is the neutral/identity element when it comes to the OR operation. As you can see, while it might not be hard to see what's happening, it's not obvious at a glance, unlike .some. However, it's also a valid way to derive the boolean result.
This approach can be further generalised to produce any result with each of the elements if you just supply it with a callback to run against each set of results. So, we can re-write it to be more generic like this:
function sequentialOperation(operation) {
return function* (mainArray) {
const iterators = mainArray.map(subArray => subArray[Symbol.iterator]());
let allResults = iterators.map(it => it.next());
while(allResults[0].done === false) {
yield operation(
allResults.map(({value}) => value)
)
allResults = iterators.map(it => it.next());
}
}
}
const sequentialOR = sequentialOperation(arr => arr.some(Boolean));
/*
arrBefore = [[true],[false],[true],[false]];
arrAfter = [true];
*/
const input1 = [[true],[false],[true],[false]];
test(input1);
/*
arrBefore = [[true, false],[false, false], [false, true], [false, false], [true, true]];
arrAfter = [true, true];
*/
const input2 = [[true, false],[false, false], [false, true], [false, false], [true, true]];
test(input2);
/*
arrBefore = [[true, false, false, false], [true, true, false, false]];
arrAfter = [true, true, false, false];
*/
const input3 = [[true, false, false, false], [true, true, false, false]];
test(input3);
/*
arrBefore = [[true, true, false, false, false], [false, false, false, false, true]];
arrAfter = [true, true, false, false, true];
*/
const input4 = [[true, true, false, false, false], [false, false, false, false, true]];
test(input4);
//a quick function to print the output
function test(input){
const output = Array.from(sequentialOR(input));
console.log(
`Input: ${JSON.stringify(input)}
Output: ${JSON.stringify(output)}`
);
}
Thus we can also easily derive other operations, for example:
const sequentialAND = sequentialOperation(arr => arr.every(Boolean)); //or arr.reduce((a, b) => a && b, true)
const sequentialAdd = sequentialOperation(arr => arr.reduce((a, b) => a + b, 0));
const sequentialMax = sequentialOperation(arr => arr.reduce((a, b) => Math.max(a, b), -Infinity));
//and so on
[ [true, true], [true] ]? and if so, what is the expected output then? Oh, and do you absolutely need to usemapandreduce? Because there might be more appropriate tools.