js数组之排列组合

这是一个面试题,题目大概就是这样子的:
有以下种类:容量=[“16G”,”32G”,”64G”];颜色=[“黑色”,”白色”,”土豪金”];网络=[“移动版”,”联通版”,”通用版”];请写出能计算出组合所有机型的函数。返回的机型组合如下[16G,”黑色,”移动版”],[16G,”白色,”移动版”]…,在手机增加属性后,函数能自动返回新的组合。

这个就类似数学的排列组合,比如我们有这几个数组:

a=[1,2,3]
b=[‘A’,’b’];

那么数组排列的情况就有3*2=6;用代码的实现就是这样:

1
2
3
4
5
6
7
8
9
10
11
var a=[1,2,3];
var b=["A","b"];
var newArr=[];
var index=0;
for(var i=0;i<a.length;i++){
for(var j=0;j<b.length;j++){
newArr[index]=[a[i]].concat(b[j]);
index++
}
}
console.log (newArr);//[[1,'A'],[1,"b"],[2,"A"],[2,"b"],[3,"A"],[3,"b"]];

打印结果:
示意图1

这是只有两个数组,如果数组个数增加到几个或十几、二十个呢,不可能嵌套几十个for循环吧,所以我现在能想到的比较简单直观的方法就是递归了。
先说一下思路,比如有这些数据:
var a=[1,2,3];
var b=[“A”,”b”];
var c=[‘KK’,”DD”];

  1. 先返回a、b整合后的数组newAB: [[1,’A’],[1,”b”],[2,”A”],[2,”b”],[3,”A”],[3,”b”]];
  2. 将newAB和c传入函数重新整合数组newABC: [[1,’A’,’KK’],[1,”b”,’kk’],[2,”A”,’kk’],…];
  3. 以此类堆下去,直到整合后的子数组长度为1,就返回结果。如[[[…],[…],…]]

代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function combineArray(arr){
//如果传进来的arr不是数组或者是空数组,就退出函数
if(arr instanceof Array !== true || arr.length<=0)return;
var len=arr.length;
//如果传入的数组长度大于等于2,则重组数组
if(len>=2){
//记录循环次数
var index=0;
//ab重组的新数组
var _tempArray=[];
for(var i=0;i<arr[0].length;i++){
for(var j=0;j<arr[1].length;j++){
if(arr[0][i] instanceof Array ){
//如果arr[0][i]是数组,则直接跟arr[1][j]合并成新数组
_tempArray[index]=arr[0][i].concat(arr[1][j]);
}else{
//如果arr[0][i]不是数组,则需要将arr[0][i]转成数组后再跟arr[1][j]合并成新数组
_tempArray[index]=[arr[0][i]].concat(arr[1][j]);
}
index++;
}
}
//新数组:重组数组和后续数组的合并
var newArr=[];
//新数组的第一个值存入_tempArray
newArr[0]=_tempArray;
//新数组的第2个值就应该存入arr[2](因为我们每次都会拿arr[0],arr[1]重组),以此类堆
for(var k=2;k<arr.length;k++){
newArr[k-1]=arr[k];
}
//将newArr传入combineArray函数,递归执行,直到len=1时执行else语句
combineArray(newArr);
}else{
//否则直接返回数组的第一个值
return arr[0];
}

}
var arr=[[1,2,3],["A","b"],['KK',"DD"]];
console.log(combineArray(arr));

执行结果输出:
示意图2

热评文章