今天我给自己定的工作任务是一个课题研究,如何用JS脚本根据未知个数的数组组合生成矩阵,具体情况是,假如该商品有颜色套餐款式三种规格组,每种规格组也有如下的规则:

var arr = new Array(
	new Array('套餐1', '套餐2'),
	new Array('紅色', '藍色', '黑色'),
	new Array('欧式', '中式')
);

我需要将其转换成如下格式:

var variation_set = new Array(
	"套餐1,紅色,欧式",
	"套餐1,紅色,中式",
	"套餐1,藍色,欧式",
	"套餐1,藍色,中式",
	"套餐1,黑色,欧式",
	"套餐1,黑色,中式",
	"套餐2,紅色,欧式",
	"套餐2,紅色,中式",
	"套餐2,藍色,欧式",
	"套餐2,藍色,中式",
	"套餐2,黑色,欧式",
	"套餐2,黑色,中式"
)

假如规格组只有3个,很好办:

var variation_set = new Array();
for (var a in arr[0]) {
	for (var b in arr[1]) {
		for (var c in arr[2]) {
			variation_set.push(arr[0][a], arr[1][b], arr[2][c]);
		}
	}
}

但是在文章开篇的课题里我已经描述了,现在规格组的数量是未知的,在面对未知的对象的时候,最好的解决方法非递归不可了。

我的思路是,首先,在函数中用for循环遍历第一个数组,并且将该数组的当前键值保存在一个临时变量里,然后判断这是否是最后一个数组。

如果是最后一个,则将临时变量转换成字符串,push到variation_set。

如果不是最后一个,则递归调用函数遍历下一个数组,同样将键值保存到临时变量中,一直到最后一个:

var variation_set = value = new Array();  
function getMatrix(arr, index, value) {	 
	for (var a in arr[index]) {
		if (index==0) value = new Array(); //如果是首轮,清空value数组
		value.push(arr[index][a]);
		if (index==arr.length-1) {
			variation_set.push(value.toString());
		} else {
			index++;
			getMatrix(arr, i, value);
		}
	}
}
getMatrix(arr, 0, value);

很快,我发现了一个问题,在判断是否是最后一个的时候,我将递归的index索引函数+1了,所以发现返回的每一个结果都是第一个函数的第一个键值开头的,于是我使用另一个变量i代表index++。

var variation_set = value = new Array();  
function getMatrix(arr, index, value) {	 
	for (var a in arr[index]) {
		if (index==0) value = new Array(); //如果是首轮,清空value数组
		value.push(arr[index][a]);
		if (index==arr.length-1) {
			variation_set.push(value.toString());
		} else {
			var i = index + 1; //避免使用index++而不会调用arr[0][0]之外的其他键值
			getMatrix(arr, i, value);
		}
	}
}
getMatrix(arr, 0, value);

新的问题出现了,虽然我设置了如果是首轮清空value数组,但前两个还正常,从第三轮里返回的值里有上一轮的键值。研究后发现是因为在某一轮完结之后并不会跳到首轮重新开始,可以会从第二轮开始遍历,这样因为value变量没有被清空,所以还保留了上一轮的一些键值。

怎么解决这个问题呢,我苦思冥想,突然灵光闪现,每一组的规格数和规格组的总数是一样的,所以我只要保证第一轮的时候临时变量value数组是空的,第二轮只有1个键值,第三轮只有2个键值,以此类推:

var variation_set = value = new Array();  
function getMatrix(arr, index, value) {	 
	for (var a in arr[index]) {
		value.splice(index, value.length-index); //删除该层不应该有的数组键值
		value.push(arr[index][a]);
		if (index==arr.length-1) {
			variation_set.push(value.toString());
		} else {
			var i = index + 1; //避免使用index++而不会调用arr[0][0]之外的其他键值
			getMatrix(arr, i, value);
		}
	}
}
getMatrix(arr, 0, value);

好了,测试的结果是正确的,好兴奋。最终调试variation_set的结果给了我当头一棒。怎么回事?经过一番焦躁地调试,发现问题处在第一句代码,导致variation_set会随着value的值变化而变化,这两个变量会相互干扰。并且我发现value变量不是必要的,稍加修改,完美的代码终于诞生啦:

var variation_set = new Array();
function getMatrix(arr, index, value) {
	for (var a in arr[index]) {
		value.splice(index, value.length-index); //删除该层不应该有的数组键值
		value.push(arr[index][a]);
		if (index==arr.length-1) {
			variation_set.push(value.toString());
		} else {
			var i = index + 1; //避免使用index++而不会调用arr[0][0]之外的其他键值
			getMatrix(arr, i, value);
		}
	}
	return variation_set;
}
getMatrix(arr, 0, new Array());

TADA~!好崇拜我自己……特此日志留念!

喜欢这篇文章吗,不妨分享给朋友们吧!