Как перемешать каждый второй столбец с помощью скрипта Google Apps? - PullRequest
1 голос
/ 12 февраля 2020

Я хочу рандомизировать D: E, F: G, H: I, J: K, если C равно 4, с помощью скрипта Google Apps.

В данный момент я использую этот неэффективный и трудоемкий код:

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 должна быть рандомизирована. Столбцы для нескольких строк не следует менять на одну и ту же позицию.

1 Ответ

2 голосов
/ 12 февраля 2020

Почему так медленно?

  • Использование getValues ​​внутри l oop значительно замедляет сценарий. Пакетные операции важны.

Поток скриптов:

  • Создайте случайный массив чисел от 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;
    })
  );
}

Список литературы:

...