您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

jQuery数组的特定组合的串联,除非重复

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()第一次调用要使用的长度。像这个:

function getLength(color) {
  var r=1;
  for(var i in color)
    r*=color[i].length;
  return r;
}

现在,假设您有一个数组column一个数组color

var arrangedArrays=arrangeArrays(column, color);
var res=go(new Array(), arrangedArrays["column"], arrangedArrays["color"], 0, getLength(arrangedArrays["color"]), 0);

在这里看起来似乎很大,但是我想很好地解释一下,无论如何,如果您删除代码和示例中的注释,就没有那么大了……整个事情就是不要对这些索引发疯了;)

效果不佳…效果不佳。

您可以使用“关联数组”(或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的键相同。

最后一件事:我没有测试代码,它可能会漏掉一点,或者可能有些混乱。目的是帮助,而不是做:)

祝你好运!

JS 2022/1/1 18:46:19 有329人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶