首先我们要知道什么是笛卡尔积?
百度百科
> 笛卡尔乘积是指在数学中,两个集合X和Y的笛卡尔积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员。笛卡尔积的符号化为:
A×B={(x,y)|x∈A∧y∈B}
例如,A={a,b}, B={0,1,2},则
A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}
B×A={(0, a), (0, b), (1, a), (1, b), (2, a), (2, b)}
那些场景会用到笛卡尔积呢?
- SQL中:
select * from tbl_a, tbl_b;
查询的结果就是表tbl_a与表tbl_b的笛卡尔积。 - 电商的商品中的销售属性决定了商品中的SKU数。比如:苹果11,颜色:黄色/绿色/红色/银色,存储:64GB/128GB/256GB,则我们可以购买的SKU就有4*3=12种。
颜色 | 存储 |
---|---|
黄色 | 64GB |
黄色 | 128GB |
黄色 | 256GB |
绿色 | 64GB |
绿色 | 128GB |
绿色 | 256GB |
红色 | 64GB |
红色 | 128GB |
红色 | 256GB |
银色 | 64GB |
银色 | 128GB |
银色 | 256GB |
现在我们就电商商品的销售属性距离来实现。当然网上也存在着各种版本的实现。在此我也就不再重复写了。有兴趣的同学可以百度/Google一下。
下面是我个人的想法实现的,扩展性更强。
// 属性数组
var props = [['黄色','绿色','红色','银色'],['64GB','128GB','256GB']];
/**
* 笛卡尔积计算sku总数
*/
var descartes = (pre = [], suf = []) => {
if(!pre || pre.length < 1){
return suf;
}
let result = [];
pre.forEach(o1 => {
suf.forEach(o2 => {
result.push(o1 + ',' + o2);
})
})
return result;
};
(function main(props){
// 定义最终的结果集
var res = [];
// 循环属性列表 - 支持N种属性
props.forEach(t => {
res = descartes(res, t);
//console.log(res);
})
console.log('笛卡尔积后:', res);
// 逆向
props.reverse();
res = [];
props.forEach(t => {
res = descartes(res, t);
//console.log(res);
})
console.log('逆向笛卡尔积后:', res);
})(props);
在浏览器控制台运行结果:
实际使用情况:
// 属性数组
var props = [{"id": "p1", "name":"颜色","value":[{"id":"v1","name":'黄色'},{"id":"v2","name":'绿色'},{"id":"v3","name":'红色'},{"id":"v4","name":'银色'}]},{"id": "p2", "name":"存储ROM","value":[{"id":"v5","name":'64GB'},{"id":"v6","name":'128GB'},{"id":"v7","name":'256GB'}]}];
/**
* 笛卡尔积计算sku总数
*/
var descartes = (last = [], cursor = {}) => {
let result = [];
let id = cursor.id;
let name = cursor.name;
last.forEach(o1 => {
(cursor.value || []).forEach(o2 => {
// 深拷贝
let temp = JSON.parse(JSON.stringify(o1));
temp[id] = {name,"pvId": o2.id,"pvName":o2.name};
result.push(temp);
})
})
return result;
};
(function main(props){
// 定义最终的结果集
var res = [{}];
// 循环属性列表 - 支持N种属性
props.forEach(t => {
res = descartes(res, t);
//console.log(res);
})
console.log('笛卡尔积后:', res);
// 逆向
props.reverse();
res = [{}];
props.forEach(t => {
res = descartes(res, t);
//console.log(res);
})
console.log('逆向笛卡尔积后:', res);
})(props);