Взвешенный случайный в таблицах Google

#google-apps-script #google-sheets

#google-apps-script #google-sheets

Вопрос:

У меня три сотрудника: Джон, Эшли и Марк. В течение дня мы продолжаем получать задания от наших клиентов. Я хочу, чтобы 20% заданий отправлялись Джону, 50% для Эшли и 30% для Марка, и для этого я пытаюсь создать таблицы Google, которые случайным образом выбираются в соответствии с этими весами (20%, 50% и 30%).). Вы можете увидеть его в этом файле таблиц Google.

Способ, который я нашел, сначала казался хорошим, проблема в том, что он использует функцию RANDBETWEEN и продолжает рандомизировать каждый раз, когда что-то происходит на листе, поэтому это может выглядеть так:

введите описание изображения здесь

И если я просто добавлю одну строку, она полностью изменится:

введите описание изображения здесь

Есть ли способ исправить рандомизацию (возможно, скопировать-вставить значения через скрипт?) или альтернативный способ сделать то же самое?

Ответ №1:

Вы можете выполнить это с помощью пользовательской функции, созданной в Google Apps Script, и использовать Math.random() для достижения случайности. В отличие RANDBETWEEN от этого, он не будет обновляться каждый раз при редактировании листа или даже при обновлении самой электронной таблицы. Для этого также не потребуются данные A6:B16 (людей и процентов A2:B4 будет достаточно).

Для этого выполните следующие действия:

  • В электронной таблице выберите Сервис> Редактор сценариев, чтобы открыть скрипт, привязанный к вашему файлу.
  • Скопируйте эту функцию в редакторе сценариев и сохраните проект:
 function GET_RANDOM_PERSON(values) { // "A2:B4"
  const random = Math.random(); // Random number between 0 and 1
  const sheet = SpreadsheetApp.getActiveSheet();
  // Change range if needed. Range could be a function argument if preferred:
  if (!values) values = sheet.getRange("A2:B4").getValues();
  let acc = 0;
  values = values.map(value => {
    acc = acc   value[1];
    return [value[0], acc]; // Return accumulated probabilities
  });
  // Return person getting the job:
  return values.find(value => value[1] > random)[0];
}
  
  • Теперь, если вы вернетесь к своей электронной таблице, вы можете использовать эту функцию, как если бы вы использовали обычную формулу sheets, как вы можете видеть здесь:

введите описание изображения здесь

Ссылка:

Комментарии:

1. Это очень помогает! Можем ли мы настроить людей и%s для выбора в таблице как обычную функцию?

2. @abutremutante Я изменил свой пример кода так, чтобы функция принимала диапазон в качестве аргумента, например =GET_RANDOM_PERSON(A2:B4) . Я надеюсь, что это полезно для вас.

3. if (!values) values = sheet.getRange("A2:B4").getValues() разве это тоже не должно быть изменено?

4. @abutremutante Я добавил это, чтобы существовал диапазон входных значений по умолчанию на случай, если аргумент не указан. Вы можете удалить эту строку, если не хотите иметь диапазон по умолчанию.

Ответ №2:

С вашей текущей формулой и настройкой, а также без скриптов, вы можете сделать это с помощью итеративного вычисления:

  1. Включите итеративный расчет: Файл> Настройки электронной таблицы> Расчет
  2. Поставьте галочку. (Я буду использовать ячейку F2)
  3. Измените свои формулы, чтобы они выглядели следующим образом:
 =IF($F$2;
  vlookup(RANDBETWEEN(1;10);$A$6:$B$16;2;0);
E2)
  

Если флажок установлен, ячейки будут вычислять новые случайные значения при изменении. Если флажок не установлен, он будет предотвращать любые изменения, пока не будет установлен снова. (Проверено = разблокировано).

При первом вводе формулы она инициализируется значением 0. Установите флажок, чтобы сгенерировать первый список.