简体   繁体   English

Google 表格随机复制并使用脚本排序

[英]Google Sheets Random Copy and Sort with Scripts

What I'm attempting to do is copy a column over and re-sort it.我想要做的是复制一列并重新排序。 Problem is, it captures all available cells and uses the same space to re-sort, causing blank spaces.问题是,它捕获所有可用的单元格并使用相同的空间重新排序,从而导致空白。 The idea is to create tournament match pairings, with the first column being the Roster itself, and following columns being players they will be matched against.这个想法是创建锦标赛配对,第一列是花名册本身,后面的列是他们将与之匹配的球员。

I'd also like to add a line that verifies a name doesn't appear twice on the same row, reshuffling until the column is all unique along each row我还想添加一行来验证名称不会在同一行中出现两次,重新洗牌直到每一行的列都是唯一的

This is the code I have so far.这是我到目前为止的代码。 I attempted to filter the data by swapping我试图通过交换来过滤数据

  range2.setValues(shuffleArray(range.getValues()));

for为了

  range2.setValues(shuffleArray(range.getValues().filter(String)));

but this results in a "Number of data rows is 10 when range is 41" error, not verbatim obviously.但这会导致“范围为 41 时数据行数为 10”错误,显然不是逐字记录。 I'm trying to collapse the blank spaces that are shown in this Screenshot .我试图折叠此屏幕截图中显示的空白区域。

I'm sure I can figure out how to expand it by however many matches I wish to generate.我确信我可以想出如何通过我希望生成的匹配项来扩展它。

function shuffleRange() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('SETUP');
  var range = sheet.getRange('A31:A')
  var range2 = sheet.getRange('C31:C');
  range2.clearContents;
  range2.setValues(shuffleArray(range.getValues()));
}

function shuffleArray(array) {
  var i, j, temp;
  for (i = array.length - 1; i > 0; i--) {
    j = Math.floor(Math.random() * (i+1));
    temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}

EDIT::::: Code has been moved to a test sheet hence different name and ranges, ive adjusted the samples when i moved them of course编辑:::::代码已移至测试表,因此名称和范围不同,我当然在移动样本时调整了样本

function shuffleRange() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet4');
  var range = sheet.getRange('A1:A40')
  var v = range.getValues().filter(String);      
        
      //Match 1
  var values = shuffleArray1(v);
  while (v.length != [...new Set(values.map(([a]) => a))].length) {
    values = shuffleArray1(v);  
  }
  range.offset(0, 1, values.length).setValues(values);

      //Match 2
  var values2 = shuffleArray2(v);
  while (v.length != [...new Set(values2.map(([a]) => a))].length) {
    values = shuffleArray2(v);  
  }
  range.offset(0, 2, values.length).setValues(values2);
}

function shuffleArray1(array) {
  var i, j, temp;
  for (i = array.length - 1; i > 0; i--) {
    j = Math.floor(Math.random() * (i+1));
    temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}

function shuffleArray2(array) {
  var u, v, temp;
  for (u = array.length - 3; u > 0; u--) {
    v = Math.floor(Math.random() * (u+2));
    temp = array[u];
    array[u] = array[v];
    array[v] = temp;
  }
  return array;
}

Modification points:修改点:

  • I think that range2.clearContents might be range2.clearContent() .我认为range2.clearContents可能是range2.clearContent()
  • In your script, by sheet.getRange('A31:A') , all rows in the sheet are retrieved.在您的脚本中,通过sheet.getRange('A31:A') ,检索工作表中的所有行。

When these points are reflected in your script, how about modifying shuffleRange() as follows?当这些点反映在你的脚本中时,如何修改shuffleRange()如下?

Modified script:修改脚本:

function shuffleRange() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('SETUP');
  var lastRow = sheet.getLastRow();
  var range = sheet.getRange('A31:A' + lastRow);
  var range2 = sheet.getRange('C31:C' + lastRow);
  range2.clearContent();
  var values = shuffleArray(range.getValues()).filter(String);
  range.offset(0, 2, values.length).setValues(values);
}
  • I'm not sure about the last row of your sheet.我不确定你表格的最后一行。 So, I proposed the above modification.所以,我提出了上面的修改。

Added 1:添加 1:

From your following new question,从您的以下新问题中,

essentially if the row contains a duplicate it has to reshuffle until each row contains a unique name from the original column, to create unique match pairings for tournaments, this will check the whole row, as some tournaments run only 2 matches, some up to 21本质上,如果该行包含重复项,则必须重新洗牌,直到每一行都包含原始列中的唯一名称,才能为锦标赛创建唯一的比赛配对,这将检查整行,因为有些锦标赛只进行 2 场比赛,有些比赛最多 21 场

In this case, how about the following sample script?在这种情况下,下面的示例脚本怎么样?

Sample script:示例脚本:

function shuffleRange() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('SETUP');
  var lastRow = sheet.getLastRow();
  var range = sheet.getRange('A31:A' + lastRow);
  var range2 = sheet.getRange('C31:C' + lastRow);
  range2.clearContent();
  var v = range.getValues().filter(String);
  var values = shuffleArray(v);
  while (v.length != [...new Set(values.map(([a]) => a))].length) {
    values = shuffleArray(v);
  }
  range.offset(0, 2, values.length).setValues(values);
}
  • In this case, when the duplicated values are included in values , shuffleArray function is run again.在这种情况下,当重复值包含在values中时,将再次运行shuffleArray function。

Added 2:添加2:

From your following reply,从您的以下回复中,

Unfortunately it produced duplicate lines almost immediately once i duplicate the functions to create a second set of results不幸的是,一旦我复制函数以创建第二组结果,它几乎立即产生重复行

I added a new sample so you can see how im trying to expand it across several columns of results, this will create a set number of matches.我添加了一个新示例,这样您就可以看到我是如何尝试将它扩展到多列结果中的,这将创建一定数量的匹配项。 I will, when done, swap the counter for a cell check so a user can set the match number, but thats later完成后,我会将计数器换成单元格检查,以便用户可以设置匹配号,但那是以后的事

Sample script:示例脚本:

function shuffleRange() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('SETUP');
  var range = sheet.getRange('A1:A40');
  var v = range.getValues().filter(String);

  var createValues = v => {
    SpreadsheetApp.flush(); // I'm not sure whether this line is required.
    var temp = sheet.getRange(1, 1, 40, sheet.getLastColumn()).getValues();
    var existValues = temp[0].map((_, c) => temp.map(r => r[c]).join("")).filter(String);
    var values;
    do {
      values = shuffleArray1(v);
      while (v.length != [...new Set(values.map(([a]) => a))].length) {
        values = shuffleArray1(v);
      }
      var check = values.map(([a]) => a).join("");
    } while (existValues.some(e => e == check));
    return values;
  }

  var values1 = createValues(v);
  range.offset(0, 1, values1.length).setValues(values1);

  var values2 = createValues(v);
  range.offset(0, 2, values2.length).setValues(values2);
}
  • In this modification, the new column values are created by checking all existing columns.在此修改中,新列值是通过检查所有现有列来创建的。

Adding to Tanaike's suggestion I've joined your two functions in order to be able to re-shuffle.添加到 Tanaike 的建议中,我加入了你的两个功能,以便能够重新洗牌。 I'm not as well-versed in coding, and probably there's a more-alike version of your code that also enables the re-shuffling.我不太精通编码,可能有一个更相似的代码版本也可以重新洗牌。 But you can try this:但你可以试试这个:

 function shuffleRange() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('SETUP');
  var lastRow = sheet.getLastRow()
  var range = sheet.getRange('A31:A' + lastRow);
  var range2 = sheet.getRange('C31:C' + lastRow);
  range2.clearContents;
      function shuffleArray() {
        var i, j, temp;
        var array = range.getValues()
        var array2 = range.getValues()
        var count= 1;
        while (count>0){
          count=0
          for(i=array.length-1;i>0;i--){
            j = Math.floor(Math.random() * (i+1));
            temp = array2[i];
            array2[i] = array2[j];
            array2[j] = temp;
          }

            for(i=0;i<array.length;i++){
             if(array[i].toString() == (array2[i]).toString()){count = count+1}
            }}
        return array2
      }

  range2.setValues(shuffleArray())
}

I've make it try tenths of times and never got a duplicate:我已经尝试了十分之一次,但从来没有重复过:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM