javascript对象属性的笛卡尔积

javascript对象属性的笛卡尔积,javascript,cartesian-product,Javascript,Cartesian Product,我有一个如下形式的对象(下面是简化的测试用例) 我希望生成属性的笛卡尔积,以便输出为以下形式的数组: // desired output [ {shirts:{sizes:'large', color:'red'}, trousers:{type:'formal', pattern:'plaid'}} ,{shirts:{sizes:'large', color:'red'}, trousers:{type:'formal', pattern:'stripes'}} ,{shirts:

我有一个如下形式的对象(下面是简化的测试用例)

我希望生成属性的笛卡尔积,以便输出为以下形式的数组:

// desired output

[ {shirts:{sizes:'large', color:'red'}, trousers:{type:'formal', pattern:'plaid'}}
  ,{shirts:{sizes:'large', color:'red'}, trousers:{type:'formal', pattern:'stripes'}}
  ,{shirts:{sizes:'large', color:'red'}, trousers:{type:'casual', pattern:'plaid'}}
  , {shirts:{sizes:'large', color:'red'}, trousers:{type:'casual', pattern:'stripes'}}
  ,{shirts:{sizes:'large', color:'blue'}, trousers:{type:'formal', pattern:'plaid'}}
..... and so on  ]
我怎样才能做到这一点?我编写了下面的代码(基于另一篇SO文章中对数组笛卡尔积的代码的修改),但我似乎正绞尽脑汁试图让它工作

 function myCartesianProduct(input, current) {
    if (!input) { return []; }


    var head = input[Object.keys(input)[0]];

    var tail = objSlice(input);

    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 (Object.keys(tail).length) {   //if tail.length
                var productOfTail =
                        myCartesianProduct(tail, newCurrent);
                output = output.concat(productOfTail);

            } else {
                output.push(newCurrent);

            }
        }
    }
    return output;
}


function objSlice(obj) {
    var slicedObj = angular.copy(obj);  // copy object using angularJs copy method
    delete slicedObj[Object.keys(slicedObj)[0]]; //delete the first key
    return slicedObj;
};

function copy(obj) {
        var res = {};
        for (var p in obj) res[p] = obj[p];
        return res;
    }

console.log(myCartesianProduct(test));
函数myCartesianProduct(输入,当前){
如果(!input){return[];}
var head=input[Object.keys(input)[0]];
var tail=objSlice(输入);
var输出=[];
用于(var键在头部){
对于(变量i=0;i

提前感谢您的帮助

好的,让我们从一个函数开始,该函数生成给定数组的乘积:

function product(args) {
    if(!args.length)
        return [[]];
    var prod = product(args.slice(1)), r = [];
    args[0].forEach(function(x) {
        prod.forEach(function(p) {
            r.push([x].concat(p));
        });
    });
    return r;
}
下一个使用
product
将类似
{a:[1,2],b:[3,4]}
的内容转换为
[{a:1,b:3},{a:1,b:4},{a:2,b:3},{a:2,b:4}]
:

function objectProduct(obj) {
    var keys = Object.keys(obj),
        values = keys.map(function(x) { return obj[x] });

    return product(values).map(function(p) {
        var e = {};
        keys.forEach(function(k, n) { e[k] = p[n] });
        return e;
    });
}
对于测试数据,必须应用两次:

var result = {};
Object.keys(test).forEach(function(k) {
    result[k] = objectProduct(test[k])
});

result = objectProduct(result);

这将为您提供所需的输出。

请参见@Paul,这种情况不同。我确实看到了关于这方面的其他帖子(并根据修改创建了代码),但有一点不同,在这种情况下,我们有嵌套的对象属性,而不是数组数组。是的,我想也许可以将子对象上的object.keys()与另一个问题中的数组笛卡尔积函数结合起来,然后用
map
var result = {};
Object.keys(test).forEach(function(k) {
    result[k] = objectProduct(test[k])
});

result = objectProduct(result);