笛卡尔积实现-JavaScript版

首先我们要知道什么是笛卡尔积?

百度百科 > 笛卡尔乘积是指在数学中,两个集合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);
实际运行结果:

在这里插入图片描述

效果图:

在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值