PlusLab.net – Looking for impossible IT project
Javascript-sum-of-Array
/* Javascript sum of Arrays
* using ideas from https://github.com/rambkk/sum-of-Array
*
* sumArrays (version 0.11 - initial release)
*
* Requirement: might require Javascript ES6
*
* (c) Ram Narula You can use this information, kindly do give credit: github rambkk - Ram Narula - pluslab.net
* Please drop a line to say hello and let me know what kind of project you are working on :-)
*/
/* Using: recursion, reduce, map, shift, iteration
* summing linear arrays: 2 of same size, 2 of different sizes, multiple of different sizes
* summing multi dimension arrays: 2 of same size, 2 of different sizes, multiple of different sizes,
* with difference in structures returning null
*
*/
/* recursion without iteration for linear 2 arrays
* NOTE: arrays can have different lengths
* clear recursion with little processing in each step
*/
function sumArrayRecursive1d_v10(a,b) {
return typeof a==='undefined' || typeof b==='undefined' ? a??b :
(a.length||b.length) ? [sumArrayRecursive1d_v10(a.shift(),b.shift()),...sumArrayRecursive1d_v10(a,b)] :
a+b
}
/* recursion without iteration for linear 2 arrays
* NOTE: arrays can have different lengths
* simple
*/
function sumArrays(a,b) {
return (a.length||b.length) ? [(a.shift()??0)+(b.shift()??0),...sumArrays(a,b)] : [];
}
/* recursion without iteration for many linear arrays
* NOTE: arrays can have different lengths
* simple
*/
function sumArrays(...a) {
return a.length===2 ?
(a[0].length||a[1].length) ? [(a[0].shift()??0)+(a[1].shift()??0),...sumArrays(a[0],a[1])] : []
: sumArrays(a.shift(),sumArrays(...a));
}
/* Making simple recusion above to work on multi dimension array
* This might look a bit complicated as it was designed for linear array
* and just adding recursion when item is an array */
function sumArrays(a,b) {
return (a?.length||b?.length) ?
[(a&&Array.isArray(a[0]))||(b&&Array.isArray(b[0])) ?
sumArrays(a.shift(),b.shift()) :
(a?.shift()??0)+(b?.shift()??0),...sumArrays(a,b)]
: [];
}
/* recursive function without iteration for many multi dimension arrays
* NOTE: arrays can have different sizes but must be same structure
* NOTE: works on many arrays
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null when corresponding item types do not match / different structures
* NOTE: blank array '[]' from input array will be kept
*/
function sumArrays(...a) {
return a.length===2 ?
typeof a[0]==='undefined' || typeof a[1]==='undefined' || (a[0].length===0 && a[1].length===0) ? a[0]??a[1]??[] :
typeof a[0] !== typeof a[1]?null :
a[0]?.length||a[1]?.length ? [sumArrays(a[0].shift(),a[1].shift()),...sumArrays(a[0],a[1])] :
a[0]+a[1]
:
sumArrays(a.shift(),sumArrays(...a))
}
/* improvement from the above function, recursive function, very simple
* NOTE: arrays can have different sizes but must be same structure
* NOTE: works on many arrays
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null when corresponding item types do not match / different structures
* NOTE: blank array '[]' from input array will be kept
* NOTE: can work with array with holes in it
*/
function sumArrays(...a) {
return a.length===2 ?
a[0]===null || a[1]===null ? null :
typeof a[0]==='undefined' && typeof a[1]==='undefined'?undefined : //both are undefined, return undefined
typeof a[0]==='undefined' || typeof a[1]==='undefined'?a[0]??a[1] : //one is undefined, return the other one
typeof a[0] !== typeof a[1]?null : //different types, return null
a[0].length===0 && a[1].length===0 ? [] : //both are empty arrays, return []
a[0]?.length||a[1]?.length ? [sumArrays(a[0].shift(),a[1].shift()),...sumArrays(a[0],a[1])] :
a[0]+a[1]
: sumArrays(a.shift(),sumArrays(...a))
}
/* sumArrays(
* [ 1, , 8,[9],[3] ,[],[]],
* [ 1, , , ,[3,4,5],[] ],
* [ 2, , , , ,[] ] ) =>
* ====================================
* [ 4, undefined, 8,[9],[6,4,5],[],[]]
*/
/* Adding linear arrays with same number of items
* NOTE: ignoring extra item in 'b', NaN if corresponding value does not exist
*/
function sumArrayLinear_v1(a,b) {
return a.map((v,k) => v+b[k]);
}
/*
* sumArrayLinear_v1([1,2,3],[2,3,4]) => [ 3, 5, 7 ]
* sumArrayLinear_v1([1,2,3,4],[2,3,4]) => [ 3, 5, 7, NaN ]
* sumArrayLinear_v1([1,2,3],[2,3,4,5]) => [ 3, 5, 7 ]
*
* Now adjusting this function to retain the items of 'a' even if the corresponding value does not exist in 'b'
* NOTE: ignoring extra item in 'b',
* NOTE: using 0 for non-existing corresponding value in 'b'
*/
function sumArrayLinear_v2(a,b) {
return a.map((v,k) => v+(b[k]??0));
}
/*
* sumArrayLinear_v2([1,2,3,4],[2,3,4]) => [ 3, 5, 7, 4 ]
*
* Sum two linear arrays, final size should be the size of the bigger array
* Using dummy Array created with the greater length of the 2 arrays for map
* map using only key value not the value of dummy Array
*
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: the fill() - filling array with 'undefined' is needed otherwise map does not work for unassigned array
* NOTE: _ is a variable, which will not be used
*/
function sumArrayLinear_v3(a,b) {
return Array(Math.max(a.length,b.length)).fill().map((_,k) => (a[k]??0)+(b[k]??0));
}
/*
* sumArrayLinear_v3([1,2],[2,3,4]) => [ 3, 5, 4 ]
* sumArrayLinear_v3([1,2,3],[2,3]) => [ 3, 5, 3 ]
*
* sumArrayLinear_v4 is similar to sumArrayLinear_v3, the array for map is filled with 'undefined' items
*/
function sumArrayLinear_v4(a,b) {
return [...new Array(Math.max(a.length,b.length))].map((_,k) => (a[k]??0)+(b[k]??0));
}
/*
* sumArrayLinear_v4([1,2],[2,3,4]) => [ 3, 5, 4 ]
* sumArrayLinear_v4([1,2,3],[2,3]) => [ 3, 5, 3 ]
*
* Sum linear arrays using recursion and shift()
* NOTE: can work on many arrays (more than 2)
* NOTE: if the corresponding value does not exist, use 0 when adding
*/
function sumArrayShift_v1(...arrays) {
return arrays.flat().length?[arrays.reduce((c,v) => c+(v.shift()??0),0),...sumArrayShift_v1(...arrays)]:[];
}
/* sumArrayLinear_v5( [1,2] , [2,3,4], [5,6,7,8] ) => [ 8, 11, 11, 8 ]
* sumArrayLinear_v5( [1,2,3], [2,3], [1] ) => [ 4, 5, 3 ]
*
* Extending this to cover multi dimension arrays with same structure
*
* NOTE: arrays can have different sizes but must be same structure
* NOTE: works on 2 arrays
* NOTE: if the corresponding value does not exist, use 0 when adding
*/
function sumArrayShift_v20(a,b) {
return ((Array.isArray(a) && a.length)||(Array.isArray(b) && b.length)) && ((a??=[]) && (b??=[])) ?
[sumArrays(a.shift(),b.shift()),...sumArrayShift_v20(a,b)]:(a??0)+(b??0);
}
/*
* Arrays can have different sizes, but must have same structure
*/
function sumArrays(...arrays) {
return arrays.flat(Infinity).length ?
[arrays.reduce((c,v,i,a) =>
Array.isArray(c) || (Array.isArray(v[0]) && (c=[])) ?
c.push(v.shift()??0) && i==a.length-1?sumArray(...c):c
:
Number.isFinite(v[0])?(c??0)+(v.shift()??0):c
,null)
,...sumArrays(...arrays)] :
[];
}
/* Extending further to return null when the structures do not match */
function sumArrays(...arrays) {
return arrays.flat(Infinity).length ?
[arrays.filter(w => w.length).reduce((c,v,i,a) =>
Array.isArray(v[0]) && (Array.isArray(c) || (c===undefined && (c=[]))) ?
c.push(v.shift()??0) && i==a.length-1 ?
sumArrays(...c) :
c
:
Number.isFinite(v[0]) && (Number.isFinite(c)||c===undefined) ?
(c??0)+(v.shift()??0) :
v.shift()&&false||null
,undefined)
,...sumArrays(...arrays)] :
[];
}
/* shift() without reduce hack like above, works on a pair at a time
* NOTE: arrays can have different sizes but must be same structure
* NOTE: works on many arrays
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null when corresponding item types do not match / different structures
* NOTE: blank array '[]' from input array will be kept
*/
function sumArrays(...arrays) {
return arrays.reduce((a,b) =>
typeof a==='undefined' || typeof b==='undefined' || (a.length===0 && b.length===0) ?
a??b??[] :
(Array.isArray(a) && Array.isArray(b)) && (a.length || b.length) ?
[sumArrays(a.shift(),b.shift()),...sumArrays(a,b)??[]] :
Number.isFinite(a)&&Number.isFinite(b) ?
a+b :
null
)
}
/* JSON.stringify(sumArrays(
* [3,1 ,23,[ ]],
* [4,1 , 4,[1,2,[]]],
* [2,[] ] )) =>
* [9,null,27,[1,2,[]]]
*/
/* shift() works on each columns of all arrays
* NOTE: works on multi dimension arrays
* NOTE: process many arrays
* NOTE: arrays can have different sizes but must be same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null item if corresponding item types do not match
*/
function sumArrays(...a) {
return a.flat(Infinity).length ?
a.some(v => Array.isArray(v)) && !a.every(v=>Array.isArray(v))?null:
Number.isFinite(a[0]) ?
a.shift()+(a.length?sumArrays(...a):0):
[sumArrays(...a.reduce((c,v) => v.length?[...c,v.shift()]:c,[])),...sumArrays(...a)]:[]
}
/* shift() , sum of array values, adding array items with same keys, recursive function
* NOTE: works on multi dimension arrays
* NOTE: process many arrays
* NOTE: arrays can have different sizes but must be same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null item if corresponding item types do not match
*/
function sumArrays(...a) {
return a.flat(Infinity).length ?
a.some(v => Array.isArray(v)) && !a.every(v=>Array.isArray(v))?null:
!Array.isArray(a[0]) ?
a.shift()+(a.length?sumArrays(...a):0):
[sumArrays(...array1Col(...a)),...sumArrays(...a)]:[]
}
//return a.length ? a[0].length ? [a[0].shift(),...arrayItem(...a.slice(1))] : [...arrayItem(...a.slice(1))] : [];
function array1Col(...a) { return a.length ? [ ...a[0].length?[a[0].shift()]:[] , ...array1Col(...a.slice(1)) ]:[]; }
/* combining the 2 functions above into a single function by using boolean hack at the end of parameter
* recursive 2 branches
*/
function sumArrays(...a) {
return typeof a[a.length-1] ==='boolean' && a.pop() ? a.length ? [ ...a[0].length?[a[0].shift()]:[] , ...sumArrays(...a.slice(1),true) ]:[]:
a.flat(Infinity).length ?
a.some(v => Array.isArray(v)) && !a.every(v=>Array.isArray(v))?null:
!Array.isArray(a[0]) ?
a.shift()+(a.length?sumArrays(...a):0):
[sumArrays(...sumArrays(...a,true)),...sumArrays(...a)]:[]
}
/* 3 recursive functions working together
* addItems get value from each sub-array item and add values together
* array1Col remove 1st item from arrays and return the array of the removed items
* sumArrays just check if the item is an array and process accordngly
* NOTE: works on multi dimension arrays
* NOTE: process many arrays
* NOTE: arrays can have different sizes but must be same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: will not work properly if array structures do not match
*/
function addSubItems(...a) { return a.flat().length ?(a[0].shift()??0) + addSubItems(...a.slice(1)):0 }
function array1Col(...a) { return a.length ? [ ...a[0].length?[a[0].shift()]:[] , ...array1Col(...a.slice(1)) ]:[]; }
function sumArrays(...a) {
return !a.flat(Infinity).length?[]:
[ (!Array.isArray(a.flat()[0]) ? addSubItems(...a) : sumArrays(...array1Col(...a)))
,...sumArrays(...a) ]
}
/* 3 recursive functions working together
* addItems just add value of array values together
* array1Col remove 1st item from arrays and return the array of the removed items
* sumArrays just check if the item is an array and process accordngly
* NOTE: works on multi dimension arrays
* NOTE: process many arrays
* NOTE: arrays can have different sizes but must be same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: will not work properly if array structures do not match
*/
function addItems(...a) { return a[0].length ?a[0].shift() + addItems(...a):0 }
function array1Col(...a) { return a.length ? [ ...a[0].length?[a[0].shift()]:[] , ...array1Col(...a.slice(1)) ]:[]; }
function sumArrays(...a) {
return !a.flat(Infinity).length?[]:
[ (!Array.isArray(a.flat()[0]) ? addItems(array1Col(...a)) : sumArrays(...array1Col(...a)))
, ...sumArrays(...a) ]
}
/* 3 recursive functions for adding multi dimensonal arrays with return null when structures are different
* NOTE: works on multi dimension arrays
* NOTE: process many arrays
* NOTE: arrays can have different sizes but must be same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null item if corresponding item types do not match
*/
function addItems(...a) { return a[0].length ?a[0].shift() + addItems(...a):0 }
function array1Col(...a) { return a.length ? [ ...a[0].length?[a[0].shift()]:[] , ...array1Col(...a.slice(1)) ]:[]; }
function sumArrays(...a) {
return !a.flat(Infinity).length?[]:
a.some(v => Array.isArray(v[0])) && !a.every(v=>Array.isArray(v[0])||v[0]===undefined) && array1Col(...a)?[null,...sumArrays(...a)]:
[ (!Array.isArray(a.flat()[0]) ? addItems(array1Col(...a)) : sumArrays(...array1Col(...a)))
, ...sumArrays(...a) ]
}
/* 3 recursive functions for adding multi dimensonal arrays with return null when structures are different
* NOTE: works on multi dimension arrays
* NOTE: process many arrays
* NOTE: arrays can have different sizes but must be same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null item if corresponding item types do not match
* NOTE: blank array '[]' from input array will be kept
*/
function addItems(...a) { return a[0].length ?a[0].shift() + addItems(...a):0 }
function array1Col(...a) { return a.length ? [ ...a[0].length?[a[0].shift()]:[] , ...array1Col(...a.slice(1)) ]:[]; }
function sumArrays(...a) {
return !a.flat().length?[]:
[ ( !a.some(v => Array.isArray(v[0])) ? addItems(array1Col(...a)) : //none are array
a.every(v=>Array.isArray(v[0])||v[0]===undefined) ? [...sumArrays(...array1Col(...a))] : //all are array
[array1Col(...a),null][1] ) //else remove the column and return null
, ...sumArrays(...a) ];
}
/*
* JSON.stringify(sumArrays(
* [],
* [12,[2],[3,4,5,6, 7 ],[1],[2] ,555, 3,[1,[]] ],
* [2 ,[4],[5,4,3,4, 7 ],[3], 6 , 7, 8,[ ],[3]] )) =>
* [14,[6],[8,8,8,10,14],[4],null,562,11,[1,[]],[3]]
*/
/* 4 recursive functions for adding multi dimensonal arrays with return null when structures are different
* exact a column and process it then next
* NOTE: works on multi dimension arrays
* NOTE: process many arrays
* NOTE: arrays can have different sizes but must be same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null item if corresponding item types do not match
* NOTE: blank array '[]' from input array will be kept
*/
function addItems(...a) { return a.length ?a.shift() + addItems(...a):0 }
function doItems(...a) {
return a.every(v=> Array.isArray(v)) ? [...sumArrays(...a)] : //all are array
a.every(v=>!Array.isArray(v)) ? addItems(...a) : //none are array
null; //else null
}
function array1Col(...a) { return a.length ? [ ...a[0].length?[a[0].shift()]:[] , ...array1Col(...a.slice(1)) ]:[]; }
function sumArrays(...a) { return !a.some(v=>v.length)?[]: [ doItems(...array1Col(...a)) , ...sumArrays(...a) ]; }
/* JSON.stringify(sumArrays(
* [1,[1,[3,5]],2,3 ,[4],[] ,2 ],
* [1,[1,[]] ,3,[ ],[] ,[3],8 ,1,2,[],9],
* [1,2 ,3,[4,1,2] ] )) =>
* ===========================================
* [3,null ,8,null ,[4],[3],10,1,2,[],9]
*/
/* one column at a time, handle array with hole
* NOTE: arrays can have different sizes but must be same structure
* NOTE: works on many arrays
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null when corresponding item types do not match / different structures
* NOTE: blank array '[]' from input array will be kept
* NOTE: can work with array with holes in it
*/
function addItems(...a) { return a.length ?(a.shift()??0) + addItems(...a):0 }
function doItems(...a) {
return a.every(v=> typeof v==='undefined') ? undefined :
a.every(v=> Array.isArray(v) || typeof v==='undefined') ? [...sumArrays(...a)] : //all are array
a.every(v=>!Array.isArray(v)) ? addItems(...a) : //none are array
null; //else null
}
function array1Col(...a) { return a.length ? [ ...a[0]?.length?[a[0].shift()]:[] , ...array1Col(...a.slice(1)) ]:[]; }
function sumArrays(...a) { return !a.some(v=>v?.length)?[]: [ doItems(...array1Col(...a)) , ...sumArrays(...a) ]; }
/* sumArrays(
* [ 1, , 8,[9],[3] ,[],[]],
* [ 1, , , ,[3,4,5],[] ],
* [ 2, , , , ,[] ] ) =>
* ====================================
* [ 4, undefined, 8,[9],[6,4,5],[],[]]
*/
/* one column at a time, handle array with hole, using map and
* NOTE: arrays can have different sizes but must be same structure
* NOTE: works on many arrays
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null when corresponding item types do not match / different structures
* NOTE: blank array '[]' from input array will be kept
* NOTE: can work with array with holes in it
*/
function sumArrays(...a) {
return a.every (v => typeof v==='undefined')?undefined
:a.every(v => Array.isArray(v) || typeof v==='undefined') ?
a.flat().length ? [ sumArrays(...a.map(v => v.shift()).filter(v => typeof v!=='undefined')), ...sumArrays(...a) ] : []
:a.every(v => !Array.isArray(v)) ? a.shift() + (a.length ? sumArrays(...a) : 0)
:null
}
/* sumArrays(
* [ 1, , 8,[9],[3] ,[],[]],
* [ 1, , , ,[3,4,5],[] ],
* [ 2, , , , ,[] ] ) =>
* ====================================
* [ 4, undefined, 8,[9],[6,4,5],[],[]]
*/
/* Using simple iteration for 2-dimension
* Adding linear arrays OR 2-dimension array with same number of items (ignoring extra items in b)
* NOTE: ignoring extra item in b, using 0 for non-existing corresponding value in b
*/
function sumArray2d(a,b) {
return a.map((v,k) => Array.isArray(v)?v.map((w,j) =>w+(b[k][j]??0)):v+(b[k]??0));
}
/*
* sumArray2d( [1,2] , [2,3,4] ) => [ 3, 5 ]
* sumArray2d( [1,2,3,[4,5],6,7] , [2,3,4,[5,6],7] ) => [ 3, 5, 7, [ 9, 11 ], 13, 7 ]
*/
/* Sum of correponding values of multidimensional arrays with same
* using recursion (doing the same when finding an array an an item)
* NOTE: ignoring extra item in 'b'
* NOTE: using 0 for non-existing corresponding value in 'b'
* NOTE: output will be incorrect if the structures are different
*/
function sumArrayRec_v1(a,b) {
return a.map((v,k) => !Array.isArray(v)?v+(b[k]??0):sumArrayRec_v1(v,(b[k]??0)));
}
/* sumArrayRec_v1( [1,2,[3,4,5],6] , [2,3,[4,5]] ) => [ 3, 5, [ 7, 9, 5 ], 6 ]
* sumArrayRec_v1( [1,2,[3,4,5],6] , [2,3,[4,5],6,7,8] ) => [ 3, 5, [ 7, 9, 5 ], 12 ]
* sumArrayRec_v1( [1,2,3] , [2,3,[4,5]] ) => [ 3, 5, "34,5" ]
* sumArrayRec_v1( [1,2,[3,4],5] , [2,3,4] ) => [ 3, 5, [ 3, 4 ], 5 ]
*/
/* Sum of correponding values of multidimensional arrays
* the two array structures can be different
* using the first array dimension for output array dimension
* NOTE: ignoring extra item in 'b'
* NOTE: using 0 for 'b' if corresponding value in b does not exist
* NOTE: using 0 for 'b' if corresponding value in b is an array
* NOTE: using value in 'a' if 'a' is array and b has value
*/
function sumArrayRec_v2(a,b) {
return a.map((v,k) => !Array.isArray(v)?v+(Array.isArray(b[k])?0:b[k]??0):sumArrayRec_v2(v,b[k]));
}
/* sumArrayRec_v2( [1,2,3] , [2,3,[4,5]] ) => [ 3, 5, 3 ]
* sumArrayRec_v2( [1,2,[3,4],5] , [2,3,4,5] ) => [ 3, 5, [ 3, 4 ], 10 ]
*/
/* Making sum of multi-dimentional arrays with same structure by not ignoring any item
* The result will be the biggest length of the 2 arrays with largest of each corresponding sub-arrays
*
* NOTE: output will be incorrect if the structures are different
* NOTE: using 0 for 'b' if corresponding value does not exist
*/
/*
*These sumArrayBig_v* do the same thing, just using different syntax
*/
function sumArrayBig_v1(a,b) {
if(!Array.isArray(b)) return a;
[a,b]=a.length>b.length?[a,b]:[b,a];
return a.map((v,k) => !Array.isArray(v)?v+(b[k]??0):sumArrayBig_v1(v,b[k]));
}
function sumArrayBig_v2(a,b) {
return Array.isArray(b) ?(a.length>b.length?a:b).map((v,k) => Array.isArray(v)?sumArrayBig_v2(v,(a.length>b.length?b:a)[k]):v+((a.length>b.length?b:a)[k]??0)):a;
}
function sumArrayBig_v3(a,b) {
return Array.isArray(b) && ([a,b]=a.length>b.length?[a,b]:[b,a])?a.map((v,k) => Array.isArray(v)?sumArrayBig_v3(v,b[k]):v+(b[k]??0)):a;
}
/* sumArrayBig_v1( [1,2,[3,4],5,[1]] , [2,3,[4],5,[6,7,8],[5,6]] ) => [ 3, 5, [ 7, 4 ] , 10, [ 7, 7, 8 ], [ 5, 6 ] ]
* sumArrayBig_v2( [1,2,[3,4],5,[1]] , [2,3,[4],5,[6,7,8],[5,6]] ) => [ 3, 5, [ 7, 4 ] , 10, [ 7, 7, 8 ], [ 5, 6 ] ]
* sumArrayBig_v3( [1,2,[3,4],5,[1]] , [2,3,[4],5,[6,7,8],[5,6]] ) => [ 3, 5, [ 7, 4 ] , 10, [ 7, 7, 8 ], [ 5, 6 ] ]
*/
/* splitting the above function into two parts, calling a separate function for dealing with each part */
function sumArrays(a,b) {
return Array.isArray(b) && ([a,b]=a.length>b.length?[a,b]:[b,a])?a.map((v,k) => doItems(v,b[k])):a;
}
function doItems(a,b) {
return [a,b].some(v=>v===null) ? null : //if any is null then return null
[typeof a,typeof b].includes('undefined') || [a.length,b.length].every(v=>v===0) ? a??b??[] : //if either is undefined return a or b, [] if both are []
[a,b].every(v=> Array.isArray(v)) ? sumArrays(a,b) : //make recursive call if both are arrays
typeof a===typeof b? a+b : //if both are same type, do something, this just adds
null //otherwise return null --- usually when the a and b are data of different types
}
/* 3 functions recursion
* Just like above, just more clear
* NOTE: works on multi dimension arrays
* NOTE: process two arrays
* NOTE: arrays can have different sizes but must be same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
* NOTE: null item if corresponding item types do not match
* NOTE: blank array '[]' from input array will be kept
*/
function doItems(...a) {
return a.includes(null) ? null :
a.every(v=> typeof v==='undefined') ? undefined : //all are undefined
a.every(v=> Array.isArray(v)||typeof v==='undefined') ? [...sumArrays(...a)] : //all are array
a.every(v=>!Array.isArray(v)||typeof v==='undefined') ? addItems(...a) : //none are array
null; //else null
}
function addItems(...a) { return a.length ?(a.shift()??0) + addItems(...a):0 }
function sumArrays(a,b) { return Array.isArray(b) && ([a,b]=a.length>b.length?[a,b]:[b,a])?a.map((v,k) => doItems(v,b[k])):a; }
/* sumArrays(
* [1,[1,[3,5]],0,3 ,[4],[] ,2 ,[1] ,2,3],
* [1,[1,[ ]],3,[] ,[] ,[3],8 ,1 ,2,2]) =>
* =========================================
* [2,[2,[3,5]],3,null,[4],[3],10,null,4,5]
*/
/* Making sum of multi-dimensional array with same structure, the number of items can be different
* null item if corresponding item types do not match
* (different structures, eg. a number in 'a' corresponds with an array in 'b')
*
* - if 'b' is undefined, return 'a'
* - if are not arrays then return 'a'+'b'
* - if both 'a' and 'b' are arrays then
* - - assign 'a' to be the longer array 'b' the shorter array
* - - do map and run the function (recursion) for each (sub-array) item
* - else return null (when types of 'a' and 'b' do not match)
*/
function sumArrayBig_v4(a,b) {
return typeof a === 'undefined' || typeof b === 'undefined' ?
a??b :
Array.isArray(a) && Array.isArray(b) ?
([a,b]=a.length>b.length?[a,b]:[b,a])[0].map((v,k) => sumArrayBig_v4(a[k],b[k])) :
Number.isFinite(a) && Number.isFinite(b) ?
a+b :
null
}
/* sumArrayBig_v4( [1] , 0 ) => null
* sumArrayBig_v4( [1,2,3,4] , [5,6,7] ) => [ 6, 8, 10, 4 ]
* sumArrayBig_v4( [1,2,[3,4],[8,9,10]] , [5,6,7] ) => [ 6, 8, null, [ 8, 9, 10 ] ]
* sumArrayBig_v4( [1,[2,3],[10,11],[13,14],15] , [5,6, [7,8,9],12] ) => [ 6, null, [ 17, 19, 9 ], null, 15 ]
* sumArrayBig_v4( [null] , [1] ) => [ null ]
*
*
*This can sum many arrays (more than 2)
*/
function sumArrays_v4(...arrays) {
return arrays.reduce((a,b)=>
typeof a === 'undefined' || typeof b === 'undefined' ?
a??b :
Array.isArray(a) && Array.isArray(b) ?
([a,b]=a.length>b.length?[a,b]:[b,a])[0].map((v,k) => sumArrays_v4(a[k],b[k])) :
Number.isFinite(a) && Number.isFinite(b) ?
a+b :
null
)
}
/* or simply: */
function sumArrays_v4(...arrays) {
return arrays.reduce((a,b)=>typeof a==='undefined'||typeof b==='undefined'?a??b:Array.isArray(a)&&Array.isArray(b)?([a,b]=a.length>b.length?[a,b]:[b,a])[0].map((v,k)=>sumArrays_v4(a[k],b[k])):Number.isFinite(a)&&Number.isFinite(b)?a+b:null);
}
/* sumArrays_v5( [1,2] , [3,4] , [5,6] ) => [ 9, 12]
* sumArrays_v5( [1,[2],3] , [4,5,6,7] , [[8],9] ) => [ null, null, 9, 7 ]
* sumArrays_v5( [1,[1,2],3] , [2,[],[],4] , [3,[1,[5,5],3],1,1,[1,2]] ) => [ 6, [ 2, null, 3 ], null, 5, [ 1, 2 ] ]
*/
/* MAINLY REDUCE */
/* Adding two linear arrays
* NOTE: if the corresponding value does not exist, use 0 when adding
*/
function sumArrays(a,b) {
return b.reduce((c,v,k) => [...c.slice(0,k),((c[k]??0)+v),...c.slice(k+1)],a);
}
/* Multiple linear arrays
* NOTE: can work on many arrays (more than 2)
* NOTE: if the corresponding value does not exist, use 0 when adding
*/
function sumArrays(...arrays) {
return arrays.reduce((d,w) => w.reduce((c,v,k) => [...c.slice(0,k),((c[k]??0)+v),...c.slice(k+1)],d));
}
/* Adding 2 multi dimension arrays, both must have same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
*/
function sumArrays(a,b) {
return b.reduce((c,v,k) => [...c.slice(0,k),Array.isArray(v)?sumArrays((c[k]??[]),v):(c[k]??0)+v,...c.slice(k+1)],a);
}
/* Adding many multi dimension arrays, all must have same structure
* NOTE: if the corresponding value does not exist, use 0 when adding
*/
function sumArrays(...arrays) {
return arrays.reduce((d,w) => w.reduce((c,v,k) => [...c.slice(0,k),Array.isArray(v)?sumArrays((c[k]??[]),v):(c[k]??0)+v,...c.slice(k+1)],d));
}