示例1:
两个数组的笛卡尔积
const arr1 = ['1','2','3'];
const arr2 = ['a','b','c'];
const result = [];
arr1.forEach(e1 => {
arr2.forEach(e2 => {
result.push(e1 + "_" + e2)
})
})
console.log(result);
结果:
N个数组的笛卡尔积
如果是N个数组怎么办?
不确定数组数量,代码没有办法写死。该如何处理?
思路:
- 先拿其中两个数组求笛卡尔积
- 然后把前面运算的结果作为新数组,与第三个数组求笛卡尔积
把前两次运算的结果作为第三次运算的参数。大家想到什么了?
没错,之前讲过的一个数组功能:Reduce
reduce函数的声明:
reduce(callback,initvalue)
callback:是一个回调函数。这个callback可以接收2个参数:arg1,arg2
- arg1代表的上次运算得到的结果
- arg2是数组中正要处理的元素
initvalue,初始化值。第一次调用callback时把initvalue作为第一个参数,把数组的第一个元素作为第二个参数运算。如果未指定,则第一次运算会把数组的前两个元素作为参数。
reduce会把数组中的元素逐个用这个函数处理,然后把结果作为下一次回调函数的第一个参数,数组下个元素作为第二个参数,以此类推。
因此,我们可以把想要求笛卡尔积的多个数组先放到一个大数组中。形成二维数组。然后再来运算:
示例2:
const arr1 = ['1', '2', '3'];
const arr2 = ['a', 'b'];
// 用来作为运算的二维数组
const arr3 = [arr1, arr2, ['x', 'y']]
const result = arr3.reduce((last, el) => {
const arr = [];
// last:上次运算结果
// el:数组中的当前元素
last.forEach(e1 => {
el.forEach(e2 => {
arr.push(e1 + "_" + e2)
})
})
return arr
});
console.log(result);
结果:
算法结合业务
来看我们的业务逻辑:
首先,我们已经有了一个特有参数的规格模板:
[
{
"k": "机身颜色",
"selected": ["红色","黑色"]
},
{
"k": "内存",
"selected": ["8GB","6GB"]
},
{
"k": "机身存储",
"selected": ["64GB","256GB"]
}
]
可以看做是一个二维数组。
一维是参数对象。
二维是参数中的selected选项。
我们想要的结果:
[
{"机身颜色":"红色","内存":"6GB","机身存储":"64GB"},
{"机身颜色":"红色","内存":"6GB","机身存储":"256GB"},
{"机身颜色":"红色","内存":"8GB","机身存储":"64GB"},
{"机身颜色":"红色","内存":"8GB","机身存储":"256GB"},
{"机身颜色":"黑色","内存":"6GB","机身存储":"64GB"},
{"机身颜色":"黑色","内存":"6GB","机身存储":"256GB"},
{"机身颜色":"黑色","内存":"8GB","机身存储":"64GB"},
{"机身颜色":"黑色","内存":"8GB","机身存储":"256GB"},
]
思路是这样:
- 我们的启点是一个空的对象数组:
[{}]
, - 然后先与第一个规格求笛卡尔积
- 然后再把结果与下一个规格求笛卡尔积,依次类推