示例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);

结果:

笛卡尔积Java简单实现_js

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);

结果:

笛卡尔积Java简单实现_js_02

算法结合业务

来看我们的业务逻辑:

首先,我们已经有了一个特有参数的规格模板:

[
  {
    "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"},
]

思路是这样:

  • 我们的启点是一个空的对象数组:[{}]
  • 然后先与第一个规格求笛卡尔积
  • 然后再把结果与下一个规格求笛卡尔积,依次类推