Home > Enterprise >  Cartesian prodocut with optional lists javascript
Cartesian prodocut with optional lists javascript

Time:06-14

I created this function which allows me to have all combinations from a list of lists:

const cartesian = (...a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())));

I have four list for example:

var l1 = ["A","B"]
var l2 = ["C"]
var l3 = ["D","E"] #optional
var l4 = ["F","G"] #optional
var list = [l1,l2,l3,l4]

Obviusly with this function i have all combination of the lists but i want to get all combinations with optnional lists. For Example the desired output is:

 1.  ["A","C"]
 2.  ["B","C"]
 3.  ["A","C","D"]
 4.  ["A","C","E"]
 5.  ["B","C","D"]
 6.  ["B","C","E"]
 7.  ["A","C","F"]
 8.  ["A","C","G"]
 9.  ["B","C","F"]
 10. ["B","C","G"]
 11. ["A","C","D","F"]
 12. ["A","C","D","G"]
 13. ["A","C","E","F"]
 14. ["A","C","E","G"]
 15. ["B","C","D","F"]
 16. ["B","C","D","G"]
 17. ["B","C","E","F"]
 18. ["B","C","E","G"]

How can i get this output?

CodePudding user response:

Your cartesian function is tailor made for exactly four input arrays. I would make a generic version that can take any number of arrays.

I would then pass the optional flags as arguments as well -- maybe as a second array -- and use that info to also generate combinations that exclude elements from the corresponding array.

Here is a recursive generator to do the job:

function* cartesian([first, ...rest], [isOptional, ...isRestOptional]) {
    if (!first) return yield [];
    let restResults = [...cartesian(rest, isRestOptional)];
    if (isOptional) yield* restResults;
    for (const value of first) {
        for (const result of restResults) {
            yield [value, ...result];
        }
    }
}
 
// demo run
const resultsIter = cartesian([["A","B"], ["C"], ["D","E"], ["F","G"]], [0, 0, 1, 1]);
for (let result of resultsIter) console.log(...result);

The output has a different order, but it gives you all combinations.

  • Related