Skip to content

Instantly share code, notes, and snippets.

@rstiller
Created September 28, 2018 07:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rstiller/156181d596288efcac24c8f26df63004 to your computer and use it in GitHub Desktop.
Save rstiller/156181d596288efcac24c8f26df63004 to your computer and use it in GitHub Desktop.
javascript cartesian product using generator functions (streaming)
/*
streaming cartesian product elements uses less memory ...
*/
const generator = cartesianProductSimplified(['a', 'b'], [1, 2, 3, 4], ['x', 'y', 'z']);
/* prints
[ 'a', 1, 'x' ]
[ 'a', 1, 'y' ]
[ 'a', 1, 'z' ]
[ 'a', 2, 'x' ]
[ 'a', 2, 'y' ]
[ 'a', 2, 'z' ]
[ 'a', 3, 'x' ]
[ 'a', 3, 'y' ]
[ 'a', 3, 'z' ]
[ 'a', 4, 'x' ]
[ 'a', 4, 'y' ]
[ 'a', 4, 'z' ]
[ 'b', 1, 'x' ]
[ 'b', 1, 'y' ]
[ 'b', 1, 'z' ]
[ 'b', 2, 'x' ]
[ 'b', 2, 'y' ]
[ 'b', 2, 'z' ]
[ 'b', 3, 'x' ]
[ 'b', 3, 'y' ]
[ 'b', 3, 'z' ]
[ 'b', 4, 'x' ]
[ 'b', 4, 'y' ]
[ 'b', 4, 'z' ]
*/
printValues(generator);
// helper function to print all values from a generator function
function printValues(generator) {
let iteration = null;
while (iteration = generator.next()) {
if (iteration.done === true) {
break;
}
console.log(iteration.value);
}
}
// helper function to construct the arguments array for the 'cartesianProduct' class
function cartesianProductSimplified(...arrays) {
let args = [];
for (let i = 1; i < arrays.length; i++) {
args = args.concat([cartesianProduct, arrays[i]]);
}
args.splice(0, 0, arrays[0]);
return cartesianProduct(...args);
}
/*
call it like this:
cartesianProduct(['a', 'b'], cartesianProduct, [1, 2, 3, 4], cartesianProduct, ['x', 'y', 'z']);
use cartesianProductSimplified to simplify it:
cartesianProductSimplified(['a', 'b'], [1, 2, 3, 4], ['x', 'y', 'z'])
*/
function* cartesianProduct(values, generator, ...generatorArgs) {
for (const value of values) {
if (generator) {
const iterator = generator(...generatorArgs);
let iteration = null;
while (iteration = iterator.next()) {
if (iteration.done === true) {
break;
}
yield [value, ...iteration.value];
}
} else {
yield [value];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment