Создайте динамический словарь в скрипте приложений Google Sheet

У меня есть столбец с данными в таблицах Google, например:

col_name
A
A
A
B
B
C

Я хочу сохранить эти данные в словаре, где значение столбца является ключом, а количество вхождений — значением:

dict = {A:3, B:2, C:1}

Я попытался перебрать список значений:

col_values = mySheet.getRange(2, col, last_row-1, 1).getValues();

С функцией:

function count_occurances_in_col(col_values){
  let occurances_dict = new Map();
  for(var i=0;i<=col_values.length;i++){
    if (occurances_dict.has(col_values[i][0])){
      let value = occurances_dict.get(col_values[i][0]);
      occurances_dict.set(col_values[i][0], value+1);
    } else {
      occurances_dict.set(col_values[i][0], 1);
    }
  }
  return occurances_dict;
};

Но вместо словаря функция возвращает undefine (возможно), потому что ключи задаются динамически (если я правильно понял по форумам — я плохо знаю JS, только python).

Могу ли я получить такой словарь с какой-либо функцией или каким-либо другим способом?

Обратите внимание, что метод getValues() возвращает значения col_values ​​в форме:

[[A], [A], [A], [B], [B], [C]]
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
79
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Это должно сработать

const col = 1;
const last_row = mySheet.getLastRow();
col_values = mySheet.getRange(2, col, last_row - 1, 1).getValues();
function count_occurances_in_col(col_values) {
    let occurances_dict = {};
    for (var i = 0; i <= col_values.length -1 ; i++) { 
        if (occurances_dict[col_values[i][0]] != undefined) {
            occurances_dict[col_values[i][0]] += 1;
        } else {
            occurances_dict[col_values[i][0]] = 1;
        }
    }
    return occurances_dict;
};
Ответ принят как подходящий

Самый простой способ получить словарь — использовать простой ванильный объект Object, например:

function countOccurances(keys = [], dict = {}) {
  keys.forEach(v => dict[v] = 1 + (Number(dict[v]) || 0));
  return dict;
}

Приведенную выше функцию можно вызвать с помощью всего лишь массива keys, и она вернет новый Object, который выглядит как { A: 3, B: 2, C: 1 }.

Функцию также можно вызвать с использованием существующего словаря, и в этом случае функция изменит этот словарь, увеличивая счетчики и добавляя ключи по мере необходимости.

Чтобы проверить функцию, попробуйте что-то вроде этого:

function test() {
  const ss = SpreadsheetApp.getActive();
  const keys = ss.getRange('Sheet1!A2:A').getValues().flat().filter(String);
  const result = countOccurances(keys);
  console.info(result);
  return result;
}

Функция test() зарегистрирует и вернет результат в формате { A: 3, B: 2, C: 1 }.

Вот пример использования Установите, чтобы получить уникальные значения col_values, а затем подсчитать количество вхождений.

Код.gs

function test() {
  try {
    let spread = SpreadsheetApp.getActiveSpreadsheet();
    let sheet = spread.getSheetByName("Test");
    let col = 1;
    let last_row = sheet.getLastRow();
    let col_values = sheet.getRange(2,col,last_row-1,1).getValues().flat();
    let keys = [...new Set(col_values)];
    let dict = {};
    keys.forEach( key => dict[key] = 0 );
    col_values.forEach( key => dict[key[0]]++ );
    console.info(dict);    
  }
  catch(err) {
    console.info("Error in test: "+err)
  }
}

Журнал выполнения

7:02:47 AM  Notice  Execution started
7:02:48 AM  Info    { A: 3, B: 2, C: 1 }
7:02:48 AM  Notice  Execution completed

Попробуйте это:

 function myfunk() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheetByName("Sheet0");
  const obj = sh.getRange(2,1,sh.getLastRow() - 1).getValues().flat().reduce((a,v,i) => {
    if (!a.hasOwnProperty(v)) {
      a[v]=1;     
    } else {
      a[v] += 1;
    }
    return a;
  },{});
  Logger.log(JSON.stringify(obj))
 }

Execution log
11:24:06 AM Notice  Execution started
11:24:03 AM Info    {"A":3,"B":2,"C":1}
11:24:08 AM Notice  Execution completed

Примечание. Все ответы других членов сообщества работают. Это сделано для предоставления дополнительной информации о том, где можно запустить код, поскольку было указано I don't know JS well, only python.

Если сценарий предназначен для использования в качестве пользовательских функций в Google Таблицах, вы можете изменить код следующим образом:

function count_occurances_in_col(col_values) {
  let occurances_dict = {};
  for (var i = 0; i < col_values.length; i++) {
    let value = col_values[i];
    if (occurances_dict[value]) {
      occurances_dict[value] += 1;
    } else {
      occurances_dict[value] = 1;
    }
  }
  console.info(occurances_dict);
  return JSON.stringify(occurances_dict);
}

Здесь используется JSON.stringify(), чтобы объект отображался в электронной таблице, и его можно использовать следующим образом:

=count_occurances_in_col(range)

ВЫХОД

На вкладке Executions скрипта Google Apps также будет отображаться что-то подобное, если вы решите сохранить console.info(occurances_dict);.

Если сценарий предназначен для использования в Google Apps Script, вы можете изменить код следующим образом:

function count_occurances_in_col() {
  var ss = SpreadsheetApp.getActiveSheet();
  var col_values = ss.getRange(2, 1, ss.getLastRow() - 1).getValues();
  let occurances_dict = {};
  for (var i = 0; i < col_values.length; i++) {
    let value = col_values[i];
    if (occurances_dict[value]) {
      occurances_dict[value] += 1;
    } else {
      occurances_dict[value] = 1;
    }
  }
  console.info(occurances_dict);
}

ВЫХОД

Это еще один способ написания сценария:

function count_occurances_in_col() {
  var ss = SpreadsheetApp.getActiveSheet();
  var col_values = ss.getRange(2, 1, ss.getLastRow() - 1).getValues();
  let occurances_dict = {};
  col_values.forEach(value => {
    var rx = new RegExp(value, 'g');
    var match = col_values.join().match(rx);
    occurances_dict[value] = match.length;
  });
  console.info(occurances_dict);
}

ВЫХОД

Другие вопросы по теме