今天我给自己定的工作任务是一个课题研究,如何用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~!好崇拜我自己……特此日志留念!