I have a 2D array like
[ [ 'B', 'O', 'C' ],
[ 'J', 'B', 'F' ],
[ 'F', 'B', 'D' ],
[ 'F', 'D', 'W' ],
[ 'N', 'F', 'X' ],
[ 'X', 'J', 'F' ],
[ 'T', 'Y', 'H' ],
[ 'R', 'Q', 'P' ] ],
And i need to group the sub-arrays such that in the resulting 3D array each group should contain only the sub-arrays with items non identical with each other's items. Besides there shouldn't be any duplicate groups such as listing the same sub-arrays in a different order.
For the given array the result is;
[ [ [ 'B', 'O', 'C' ],
[ 'F', 'D', 'W' ],
[ 'T', 'Y', 'H' ],
[ 'R', 'Q', 'P' ] ],
[ [ 'J', 'B', 'F' ],
[ 'T', 'Y', 'H' ],
[ 'R', 'Q', 'P' ] ],
[ [ 'F', 'B', 'D' ],
[ 'T', 'Y', 'H' ],
[ 'R', 'Q', 'P' ] ],
[ [ 'N', 'F', 'X' ],
[ 'T', 'Y', 'H' ],
[ 'R', 'Q', 'P' ],
[ 'B', 'O', 'C' ] ],
[ [ 'X', 'J', 'F' ],
[ 'T', 'Y', 'H' ],
[ 'R', 'Q', 'P' ],
[ 'B', 'O', 'C' ] ] ]
My code works fine but something back in my mind says i am doing some overkill and it can be done better. Any ideas how this job might be done any better?
var arr = [ [ 'B', 'O', 'C' ],
[ 'J', 'B', 'F' ],
[ 'F', 'B', 'D' ],
[ 'F', 'D', 'W' ],
[ 'N', 'F', 'X' ],
[ 'X', 'J', 'F' ],
[ 'T', 'Y', 'H' ],
[ 'R', 'Q', 'P' ] ],
result = arr.reduce((s,t,i,a) => t.used ? s
: (s.push(a.map((_,j) => a[(i+j)%a.length])
.reduce((p,c,k) => k-1 ? p.every(t => t.every(n => c.every(v => n !== v))) ? (c.used = true, p.push(c),p) : p
: [p].every(t => t.every(n => c.every(v => n !== v))) ? (c.used = true, [p,c]) : [p])),s),[]);
console.log(JSON.stringify(result,null,2))
The code is slightly complicated but in the heart of it lies;
.reduce((p,c,k) => k-1 ? p.every(t => t.every(n => c.every(v => n !== v))) ? (c.used = true, p.push(c),p) : p
: [p].every(t => t.every(n => c.every(v => n !== v))) ? (c.used = true, [p,c]) : [p]))
which will take
[ [ 'B', 'O', 'C' ],
[ 'J', 'B', 'F' ],
[ 'F', 'B', 'D' ],
[ 'F', 'D', 'W' ],
[ 'N', 'F', 'X' ],
[ 'X', 'J', 'F' ],
[ 'T', 'Y', 'H' ],
[ 'R', 'Q', 'P' ] ],
and turn it into
[ [ 'B', 'O', 'C' ],
[ 'F', 'D', 'W' ],
[ 'T', 'Y', 'H' ],
[ 'R', 'Q', 'P' ] ]
and will mark all sub arrays as used. Then we will rotate the given array with a.map((_,j) => a[(i+j)%a.length])
, up until an unused sub array is at index 0 position and repeat the same job.
['B', 'O', 'C']
), now I add another item which has no elements in common with item 1. there could be many such choices. but after adding that item, the next item will have 6 restrictions instead of 3, and which six depends on my choice of item 2. so your final result depends on both the order of the items and your iteration method. \$\endgroup\$[[1,2], [3,4], [3,5], [5,6]
. If after[1,2]
I choose[3,4]
then I can also choose[5,6]
. If after[1,2]
I choose[3,5]
then I'm done. \$\endgroup\$[[1,2], [3,4], [3,5], [5,6]]
would return `[[[1,2],[3,4],[5,6]],[[1,2],[3,5]]] \$\endgroup\$