1

var obj = {
'渠道': ["a", "b"],
'城市': ["邯郸市", "武汉"],
'stage': ["注册", "阶段一", "阶段二", "阶段三"],
‘date’: ["最近7天", "最近14天", "最近28天"]
}

要形成一系列数组如下['a', '武汉','注册','最近七天']

我现在的方式是把对象变成二维数组,然后实现

function cartesianProductOf(obj) {
  var test = obj.map(item => item);
    return Array.prototype.reduce.call(test,function(a, b) {
    var ret = [];
        a.forEach(function(a) {
        b.forEach(function(b) {
        ret.push(a.concat([b]));
      });
    });
   return ret;
  }, [[]]);
}

console.log(cartesianProductOf(a))

想问还有什么更好的方法,因为考虑到后期数据量大的问题

2个回答

0

要看你拿这个积中的元素来干什么,如果仅仅是每行,则其实这个问题换一个思路很好解决。
所谓笛卡尔积,其实质是全组合可能,这样所有可能其实可以映射为一个多位二进制整数,这个整数的每个区段对应一个原组合(1维数组),这样只要能取得一个值范围内的数,就可以很快确定一个最后积里的一行(顺序可能不严格了,但可以保证单独的行肯定是在最后数组中)。

我们分析你原始的数据,

var obj = {
'渠道': ["a", "b"], //可以对应1bit
'城市': ["邯郸市", "武汉"],//可以对应1bit
'stage': ["注册", "阶段一", "阶段二", "阶段三"],//可以对应2bit
'date': ["最近7天", "最近14天", "最近28天"]//可以对应2bit,不过要过滤11
}

这样所有的可能就映射到1个6bit的整数上,且该值的最后2bit不能是11
然后可以直接从0-(2^6-1)中过滤掉最后是11的数字就是每行有效映射,可以反解析出实际元素组合。
比如0这个数字可以对应[a,"邯郸市","注册","最近7天"]
而63因为最后2bit是11,不符合,62则对应[b, "武汉","阶段三","最近28天"]
要输出所有的组合(每1行)也很简单了(注意顺序不一定对)

let outarr=[];
for(let i=0;i<64;i++){
    if( (i&0x3)!==3 ){
        let tmp=[];
        tmp.put(obj['渠道'][i>>5]);
        tmp.put(obj['城市'][(i>>4)&0X1]);
        tmp.put(obj['stage'][(i>>2)&0X3]);
        tmp.put(obj['date'][i&0X3]);
        outarr.put(tmp);
    }
}

这样处理的好处是不涉及复杂的矩阵计算了,扩展性很好,效率也很高(是一个O(n)时间复杂度的算法,内存消耗也比较小,唯一不足是顺序性不符合严格的笛卡尔积)这就要看你如何用这些数据了。


另外建议你所有的代码都采用markdown格式处理,可以发现一些代码中的问题的。

0

666666

该答案已被忽略,原因:无意义的内容,赞、顶、同问等毫无意义的内容

撰写答案