【问题标题】:How to shuffle every second column with google apps script?如何使用谷歌应用脚​​本每隔一列洗牌?
【发布时间】:2020-02-12 07:05:30
【问题描述】:

如果 C 为 4,我想使用谷歌应用脚​​本随机化 D:E、F:G、H:I、J:K。

目前我使用这个低效且耗时的代码:

function shuffleAnswers() {
 var arr = [0, 2, 4, 6]; 
 for (var i = 2; i < lastRow()+1; i++)
 {
   var amount = sheet().getRange(i,3).getValue();
   if (amount == 4)
   {
     var source = sheet().getRange(i,4,1,2);
     var column = 4 + arr[(Math.random() * arr.length) | 0];
     var destination = sheet().getRange(i,column,1,2);
     var valuesSource = source.getValues();
     var valuesDestination = destination.getValues();
     source.setValues(valuesDestination);
     destination.setValues(valuesSource);     
   }
 }
 arr = [-2, 0, 2, 4]; 
 for (var i = 2; i < lastRow()+1; i++)
 {
   var amount = sheet().getRange(i,3).getValue();
   if (amount == 4)
   {
     var source = sheet().getRange(i,6,1,2);
     var column = 6 + arr[(Math.random() * arr.length) | 0];
     var destination = sheet().getRange(i,column,1,2);
     var valuesSource = source.getValues();
     var valuesDestination = destination.getValues();
     source.setValues(valuesDestination);
     destination.setValues(valuesSource);     
   }
 }
 arr = [-4, -2, 0, 2]; 
 for (var i = 2; i < lastRow()+1; i++)
 {
   var amount = sheet().getRange(i,3).getValue();
   if (amount == 4)
   {
     var source = sheet().getRange(i,8,1,2);
     var column = 8 + arr[(Math.random() * arr.length) | 0];
     var destination = sheet().getRange(i,column,1,2);
     var valuesSource = source.getValues();
     var valuesDestination = destination.getValues();
     source.setValues(valuesDestination);
     destination.setValues(valuesSource);     
   }
 }

 arr = [-6, -4, -2, 0]; 
 for (var i = 2; i < lastRow()+1; i++)
 {
   var amount = sheet().getRange(i,3).getValue();
   if (amount == 4)
   {
     var source = sheet().getRange(i,10,1,2);
     var column = 10 + arr[(Math.random() * arr.length) | 0];
     var destination = sheet().getRange(i,column,1,2);
     var valuesSource = source.getValues();
     var valuesDestination = destination.getValues();
     source.setValues(valuesDestination);
     destination.setValues(valuesSource);     
   }
 }
}

你有什么想法吗?也许使用 range.randomize()? C=4 的每一行都应该是随机的。多行的列不应更改为相同的位置。

【问题讨论】:

  • 水平随机化对吗?你能显示随机输出吗?
  • @TheMaster 如果我的理解是正确的,当我看到 OP 脚本的第一部分时,似乎“D2:E”列的行是随机的。每行中的列“D”和“E”不是随机的。我认为 OP 想反映到“D2:E”、“F2:G”、“H2:I”和“J2:K”。但如果我的理解不正确,我深表歉意。
  • @TheMaster 而且,当“C”列是4 时,OP 似乎想要随机化。我现在注意到了。请注意这一点。
  • @Tanaike 谢谢。操作也得到澄清。
  • @TheMaster 感谢您的回复。我注意到我的理解不正确。似乎水平箭头可能是水平随机化的。我为此道歉。我想尝试看看 OP 目标的愿景。我认为这是一个有趣的问题。

标签: google-apps-script google-sheets-api google-apps-script-addon


【解决方案1】:

为什么这么慢?

  • 在循环中使用 getValues 会大大降低脚本的速度。批处理操作很重要。

脚本流程:

  • 创建一个 1 到 8 之间的随机数字数组,例如 [[1,2,5,6,3,4,7,8]],然后将这些数字用作新行的索引。
  • 从工作表中获取所有值并仅重新排列 C=4 的行并一次性设置所有值。

示例脚本:

/* Create a Random arrray of numbers from 1 to 8 with couples
 * eg:[1,2,5,6,3,4,7,8]*/
const doubleShuffleFix = (n = 4) => {
  const generator = function*() {//TODO: boilerplate- can be avoided 
    let i = 1;
    yield i;
    while (true) {
      if (i < (n - 1) * 2) {
        yield (i += 2);
      } else {
        break;
      }
    }
  };
  const available = [...generator()];

  //Durstenfeld algo
  for (let i = available.length - 1; i > 0; i--) {
    let rand = Math.floor(Math.random() * i);
    [available[i], available[rand]] = [available[rand], available[i]];
  }
  return available.map(num => [num, ++num]).flat();
};

function shuffleAnswer() {
  const s = SpreadsheetApp.getActive().getSheetByName('Sheet1'),
    rg = s.getRange(2, 3, s.getLastRow() - 1, 9),
    values = rg.getValues();

  rg.setValues(
    values.map(row => {
      if (row[0] === 4) {
        return [4, ...doubleShuffleFix().map(num => row[num])];
      }
      return row;
    })
  );
}

参考资料:

【讨论】:

  • 注:测试前Enable v8
  • @TheMaster 我的感谢评论已被删除。不知道为什么。但是我注意到一个问题。使用您的代码后,具有 2 个答案 True 或 False 的问题字符串将设置为小写。他们应该保持这种“真”和“假”或“真”和“假”。你知道为什么吗?
  • @pabs 不确定...可能是一些类型更正...尝试.getDisplayValues(); 而不是.getValues();。我相信这会解决问题。
  • @TheMaster 是的,你是对的! .getDisplayValues(); 解决了。非常感谢您的所有帮助和参考!我从中学到了很多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 2021-10-11
  • 1970-01-01
相关资源
最近更新 更多