繁体   English   中英

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

[英]Google Sheets Random Copy and Sort with Scripts

我想要做的是复制一列并重新排序。 问题是,它捕获所有可用的单元格并使用相同的空间重新排序,从而导致空白。 这个想法是创建锦标赛配对,第一列是花名册本身,后面的列是他们将与之匹配的球员。

我还想添加一行来验证名称不会在同一行中出现两次,重新洗牌直到每一行的列都是唯一的

这是我到目前为止的代码。 我试图通过交换来过滤数据

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

为了

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

但这会导致“范围为 41 时数据行数为 10”错误,显然不是逐字记录。 我试图折叠此屏幕截图中显示的空白区域。

我确信我可以想出如何通过我希望生成的匹配项来扩展它。

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;
}

编辑:::::代码已移至测试表,因此名称和范围不同,我当然在移动样本时调整了样本

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;
}

修改点:

  • 我认为range2.clearContents可能是range2.clearContent()
  • 在您的脚本中,通过sheet.getRange('A31:A') ,检索工作表中的所有行。

当这些点反映在你的脚本中时,如何修改shuffleRange()如下?

修改脚本:

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);
}
  • 我不确定你表格的最后一行。 所以,我提出了上面的修改。

添加 1:

从您的以下新问题中,

本质上,如果该行包含重复项,则必须重新洗牌,直到每一行都包含原始列中的唯一名称,才能为锦标赛创建唯一的比赛配对,这将检查整行,因为有些锦标赛只进行 2 场比赛,有些比赛最多 21 场

在这种情况下,下面的示例脚本怎么样?

示例脚本:

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);
}
  • 在这种情况下,当重复值包含在values中时,将再次运行shuffleArray function。

添加2:

从您的以下回复中,

不幸的是,一旦我复制函数以创建第二组结果,它几乎立即产生重复行

我添加了一个新示例,这样您就可以看到我是如何尝试将它扩展到多列结果中的,这将创建一定数量的匹配项。 完成后,我会将计数器换成单元格检查,以便用户可以设置匹配号,但那是以后的事

示例脚本:

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);
}
  • 在此修改中,新列值是通过检查所有现有列来创建的。

添加到 Tanaike 的建议中,我加入了你的两个功能,以便能够重新洗牌。 我不太精通编码,可能有一个更相似的代码版本也可以重新洗牌。 但你可以试试这个:

 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())
}

我已经尝试了十分之一次,但从来没有重复过:

在此处输入图像描述

暂无
暂无

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

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