Skip to content

Instantly share code, notes, and snippets.

@IUnknown68
Created August 21, 2017 18:35
Show Gist options
  • Save IUnknown68/f633dc4cbad9b4762edaae7a8bd2940d to your computer and use it in GitHub Desktop.
Save IUnknown68/f633dc4cbad9b4762edaae7a8bd2940d to your computer and use it in GitHub Desktop.
Creates all possible combinations of all entries of multiple arrays.
const combineAll = (function() {
/**
* Returns a `forEach`-function that either, when on a leaf, calls the callback,
* or calls `combine()` when on a branch.
* @param {Function} cb Callback
* @param {Array} arrays Array of arrays containing values to be combined.
* @param {Number} level Index in `arrays` the previous recursion is processing.
* @param {Array} pathValues Array containing values up to `level`
* @param {Array} pathIndices Array containing indices up to `level`
* @return {Function} Function to be supplied to `forEach` in `combine()`-functions.
*/
const makeEach = (cb, arrays, level = 0, pathValues = [], pathIndices = []) =>
(level === (arrays.length - 1))
? (value, idx) =>
// leaf - call callback
cb(...[...pathValues, value, ...pathIndices, idx])
: (value, idx) =>
// branch - descend
combine(cb, arrays, level, [...pathValues, value], [...pathIndices, idx]);
/**
* Takes the array at `level + 1` and calls each entry with a function returned
* from `makeEach()`. The function will call `combine()` recursively for the next `level`.
* @param {Function} cb Callback.
* @param {Array} arrays Array of arrays containing values to be combined.
* @param {Number} level Index in `arrays` the previous recursion is processing.
* @param {Array} pathValues Array containing values up to `level`
* @param {Array} pathIndices Array containing indices up to `level`
*/
const combine = (cb, arrays, level, pathValues, pathIndices) => {
level += 1;
if (level < arrays.length) {
arrays[level].forEach(makeEach(cb, arrays, level, pathValues, pathIndices));
}
}
/**
* Combines all values from all arrays in `arrays` with each other. Means:
* If you pass 3 arrays `combineAll(cb, ar1, ar2, ar3)`, then your callback will
* be called `ar1.length` x `ar2.length` x `ar3.length` times, and it will be
* called with 3 values (`ar1[m]`, `ar1[n]`, `ar1[l]`).
* @param {Function} cb Callback called with `arrays.length` arguments
* once for each possible combination.
* @param {...Array} arrays Arrays containing values to be combined.
*/
const combineAll = (cb, ...arrays) => {
arrays[0].forEach(makeEach(cb, arrays));
};
return combineAll;
})();
const ar1 = ['A', 'B'];
const ar2 = ['1', '2', '3'];
const ar3 = ['x', 'y'];
combineAll((a, b, c) => console.log(`${a}.${b}.${c}`), ar1, ar2, ar3);
/*
output:
A.1.x
A.1.y
A.2.x
A.2.y
A.3.x
A.3.y
B.1.x
B.1.y
B.2.x
B.2.y
B.3.x
B.3.y
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment