Cartesian product of objects in javascript

前端 未结 2 1412
逝去的感伤
逝去的感伤 2020-12-09 22:11

I need to generate a complete set of variants based on a list of N attributes, while keeping the attribute name intact.



        
相关标签:
2条回答
  • 2020-12-09 23:02

    Heres a solution using Ramda.js

    const input = [
      {
        'colour': ['red', 'green']
      },
      {
        'material': ['cotton', 'wool', 'silk']
      },
      {
        'shape': ['round', 'square', 'rectangle']
      }
    ]
    
    const cartesianProductList = (Xs) => (
      R.reduce(
        (Ys, X) => (
          R.map(R.apply(R.append), R.xprod(X, Ys))
        ), 
        [[]],
        Xs
      )
    )
    
    const xPairs = (x, xs) => (
      R.map(R.pair(x), xs)
    )
    
    const cartesianProductObject = (objs) => (
      R.pipe(
        R.mergeAll,
        R.toPairs,
        R.map(R.apply(xPairs)),
        cartesianProductList,
        R.map(R.fromPairs),
      )(objs)
    )
    
    console.log(cartesianProductObject(input))
    <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

    0 讨论(0)
  • 2020-12-09 23:15

    Once you get rid of the ' 'i' is a global var issue', you can get to the result with this code for instance :

    var input = [
        { 'colour' : ['red', 'green'] },
        { 'material' : ['cotton', 'wool', 'silk'] },
        { 'shape' : ['round', 'square', 'rectangle'] }
    ];
    
    function cartesianProduct(input, current) {
       if (!input || !input.length) { return []; }
    
       var head = input[0];
       var tail = input.slice(1);
       var output = [];
    
        for (var key in head) {
          for (var i = 0; i < head[key].length; i++) {
                var newCurrent = copy(current);         
                newCurrent[key] = head[key][i];
                if (tail.length) {
                     var productOfTail = 
                             cartesianProduct(tail, newCurrent);
                     output = output.concat(productOfTail);
                } else output.push(newCurrent);
           }
         }    
        return output;
    }
    
    function copy(obj) {
      var res = {};
      for (var p in obj) res[p] = obj[p];
      return res;
    }
    
    
    console.log(cartesianProduct(input));
    
    0 讨论(0)
提交回复
热议问题