数据以这种方式:
[Array1] = ['blue','green', 'yellow','red','very very red'] [Array2] = ['ColumnA','ColumnB','ColumnC','ColumnD','ColumnD']
这导致两行。所需的JSON输出:
{ 'row1': {'ColumnA':'blue','ColumnB':'green','ColumnC':'yellow','ColumnD':'red'} 'row2': {'ColumnA':'blue','ColumnB':'green',,'ColumnC':'yellow','ColumnD':'very very red'} }
请注意,Array1和Array2是对。ColumnD有两种情况。
问题在于Array2可以具有任意数量的重复项(例如ColumnA的另一种情况)。
建立跟踪表的循环次数和建立索引表的前景令人生畏。
我正在寻找有关如何执行此操作的建议。我知道sql是更好的编程选择,但是我正在研究Jquery函数。
编辑: 工作解决方案;)
问题是,我实际上冲错了方向。我提出了以下想法,该想法使用了递归函数,因此使其更易于阅读。
确实,您希望拥有所有组合而没有排列。在这里,我只输入颜色的第一个字母。因此,来自:
b1 b2 g1 y1 y2 r1 r2 r3 A A B C C D D D
您想要拥有(这里的顺序就是代码的作用):
A B C D b1 g1 y1 r1 b1 g1 y1 r2 b1 g1 y1 r3 b1 g1 y2 r1 b1 g1 y2 r2 b1 g1 y2 r3 b2 g1 y1 r1 b2 g1 y1 r2 b2 g1 y1 r3 b2 g1 y2 r1 b2 g1 y2 r2 b2 g1 y2 r3
首先,我想要列/颜色数组的另一种格式,因为使用起来会更容易。我想从
[b1,b2,g1,y1,y2,r1,r2,r3] [A ,A ,B ,C ,C ,D ,D ,D]
到
[[b1,b2],[g1],[y1,y2],[r1,r2,r3]] [ A , B , C , D ]
这样,对于每个列值,我们将拥有一个匹配的子数组,该子数组包含与该列相关的所有颜色。
以下功能可以达到此目的(即使这可能不是实现此目的的最佳方法):
//column and color are the paired arrays you have as data input function arrangeArrays(column, color) { var ret=new Array(); //the returned container for the data ret["color"]=new Array(); //the color part of the returned data ret["column"]=new Array(); //the column part of the returned data var tmp=new Array(); //an internal array we'll use to switch from associative keys to normal keys //we parse the paired arrays for(var i in column) { //if the column is not an associative key in tmp, we declare it as an array if(!tmp[column[i]]) tmp[column[i]]=new Array(); //we add the color to the subarray matching its column tmp[column[i]].push(color[i]); } //now we just translate these horrible associative keys into cute array-standard integer keys for(var i in tmp) { ret["color"].push(tmp[i]); ret["column"].push(i); } //the commented code is a quick does-it-work block /* for(var i in ret["column"]) { document.write("column="+ret["column"][i]+" --- color(s)="+ret["color"][i].join()+"<br>"); } */ return ret; }
现在到了核心。每次对该函数的调用都将处理一列,实际上仅处理其中一部分,使用递归处理其他列。使用一个简化的示例,代码执行以下操作:
[[b1,b2],[y1,y2]] [ A , B ] total combinations: 2*2=4 first call for 1st column, length is 4, 2 possible values, first insert loops 4/2=2 times: b1 b1 call for 2nd column, length is 2, 2 possible values, first insert loops 2/2=1 time: b1 y1 b1 call for 3rd column, no 3rd column, coming back call for 2nd column, length is 2, 2 possible values, second insert loops 2/2=1 time: b1 y1 b1 y2 call for 3rd column, no 3rd column, coming back call for 2nd column done, coming back first call for 1st column, length is 4, 2 possible values, second insert loops 4/2=2 times: b1 y1 b1 y2 b2 b2 call for 2nd column, length is 2, 2 possible values, first insert loops 2/2=1 time: b1 y1 b1 y2 b2 y1 b2 call for 3rd column, no 3rd column, coming back call for 2nd column, length is 2, 2 possible values, second insert loops 2/2=1 time: b1 y1 b1 y2 b2 y1 b2 y2 call for 3rd column, no 3rd column, coming back call for 2nd column done, coming back call for 1st column done, coming back (returning)
这是代码,帮助您自己阅读注释;)
//results is an empty array, it is used internally to pass the processed data through recursive calls //column and color would be the subarrays indexed by "column" and "color" from the data received by arrangeArrays() //resultIndex is zero, it is used for recursive calls, to know where we start inserting data in results //length is the total of results expected; in our example, we have 2 blues, 1 green, 2 yellows, and 3 reds: the total number of combinations will be 2*1*2*3, it's 12 //resourceIndex is zero, used for recursive calls, to know what column we are to insert in results function go(results, column, color, resultIndex, length, resourceIndex) { //this case stops the recursion, it means the current call tries to exceed the length of the resource arrays; so we just return the data without touching it if(resourceIndex>=column.length) return results; //we loop on every color mentioned in a column for(var i=0;i<color[resourceIndex].length;i++) { //so for every color, we now insert it as many times as needed, which is the length parameter divided by the possible values for this column for(var j=0;j<length/color[resourceIndex].length;j++) { //ci will be the index of the final array //it has an offset due to recursion (resultIndex) //each step is represented by j //we have to jump "packs" of steps because of the loop containing this one, which is represented by i*(the maximum j can reach) var ci=resultIndex+i*(length/color[resourceIndex].length)+j; //the first time we use ci, we have to declare results[ci] as an array if(!results[ci]) results[ci]=new Array(); //this is it, we insert the color into its matching column, and this in all the indexes specified through the length parameter results[ci][column[resourceIndex]]=color[resourceIndex][i]; } //end of j-loop //we call recursion now for the columns after this one and on the indexes of results we started to build results=go(results, column, color, resultIndex+i*(length/color[resourceIndex].length), length/color[resourceIndex].length, resourceIndex+1); } //end of i-loop //we now pass the data back to the previous call (or the script if it was the first call) return results; }
我使用以下代码测试了该功能(如果您想体验每一步会发生什么,可能会很有用):
function parseResults(res) { for(x in res) { //x is an index of the array (integer) for(var y in res[x]) { //y is a column name document.write(x+" : "+y+" = "+res[x][y]); //res[x][y] is a color document.write("<br>"); } document.write("<br>"); } }
您可能还需要一个函数来告知go()第一次调用要使用的长度。像这个:
go()
function getLength(color) { var r=1; for(var i in color) r*=color[i].length; return r; }
现在,假设您有一个数组column和一个数组color:
column
color
var arrangedArrays=arrangeArrays(column, color); var res=go(new Array(), arrangedArrays["column"], arrangedArrays["color"], 0, getLength(arrangedArrays["color"]), 0);
在这里看起来似乎很大,但是我想很好地解释一下,无论如何,如果您删除了代码和示例中的注释,就没有那么大了……整个事情就是不要对这些索引发疯了;)
以下是第一个答案 ,效果不佳…效果不佳。
您可以使用“关联数组”(或eval类似对象/属性的语法,大致相同)。像这样的东西:
eval
var arrayResult=new Array(); var resultLength=0; for(var globalCounter=0;globalCounter<arrayColumn.length;globalCounter++) { //if this subarray hasn't been init'd yet, we do it first if(!arrayResult[resultLength]) arrayResult[resultLength]=new Array(); //case: we already inserted a color for the current column name if(arrayResult[resultLength][arrayColumn[globalCounter]]) { //1: we copy the current subarray of arrayResult to a new one resultLength++; arrayResult[resultLength]=new Array(); for(var i=0;i<=globalCounter;i++) arrayResult[resultLength][arrayColumn[i]]=arrayResult[resultLength-1][arrayColumn[i]]; //2: we replace the value for the conflicting colmun arrayResult[resultLength][arrayColumn[globalCounter]]=arrayColor[globalCounter]; //case: default, the column wasn't already inserted } else { //we simply add the column to each subarray of arrayResult for(var i=0;i<=resultLength;i++) arrayResult[i][arrayColumn[globalCounter]]=arrayColor[globalCounter]; } }
从这里开始,我想很容易将其转换为JSON格式。
解析子数组时,请记住, 关联键实际上是方法 ,即,您不能使用循环for(x=0;x<array.length;x++),而应使用for(x in array); 并且您必须测试密钥,并确保在处理之前以“ column”开头(否则您将结束对“ length” / 0 ^^对的处理)。如果您希望此容器数组具有这种键,则对arrayResult的键相同。
for
,而应
for(x in array)
最后一件事:我没有测试代码,它可能会漏掉一点,或者可能有些混乱。目的是帮助,而不是做:)
祝你好运!