Как группировать и подсчитывать данные массива по определенному критерию?

Рейтинг: 0Ответов: 1Опубликовано: 20.03.2023

У меня скрипт, который считывает идентичные значения по странам и по идентичной стране проводит операции, т.е. там где Италия значения с колонки D вычитает значения по Италии с колонок B и F, а новое значение уже в целом по Италии вставляет в новый диапазон где столбцы G и H и так по остальным странам. Не понимаю, мой скрипт не фильтрует идентичные значения, и я не понимаю, что делать дальше.

https://docs.google.com/spreadsheets/d/1v1fOkfyhmcvndLqJQE7l1et9fjAc21v82lyLarYj60g/edit#gid=0

function Balance() {
  let ss = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = ss.getSheetByName('data');
  let lr = sheet.getLastRow();

  let range = sheet.getRange(2, 1, lr, 6).getValues();
  let setrange = sheet.getRange(2, 7, lr, 2).setValues(newarr);

  let newarr = range.map(calc);
}

function calc(item) {
  return [item[2] + item[3] - item[5]];
}

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

Ответы

▲ 1Принят

В таких задачах мне нравится использовать преобразование массивов к массивам объектов, чтобы не следить за порядком колонок и не думать, куда добавлять результат. Основное решение заключается в том, чтобы собрать уникальные ключи через reduce и пересчитать для каждого вхождения результат. Также можно считать суммы, количество и т.п.

function groupOperationsByAppsScript() {
  const sheet = SpreadsheetApp.getActive().getSheetByName('Групповые операции скриптами');
  const values = toCollection_(sheet.getDataRange().getValues());

  const data = values.reduce((a, c) => {
    const outs = c['направление расходов'].__val;
    if (outs) {
      if (!a[outs])
        a[outs] = {
          result: 0,
        };
      a[outs].result += c['расходы'].__val;
    }

    const ins = c['направление прибыли'].__val;
    if (ins) {
      if (!a[ins])
        a[ins] = {
          result: 0,
        };
      a[ins].result += c['прибыль'].__val;
    }

    const adins = c['направление доп. расходов'].__val;
    if (adins) {
      if (!a[adins])
        a[adins] = {
          result: 0,
        };
      a[adins].result -= c['доп. расходы'].__val;
    }

    return a;
  }, {});

  const directs = [];
  const balance = [];

  Object.keys(data)
    .sort()
    .forEach((key) => {
      directs.push([key]);
      balance.push([data[key].result]);
    });

  sheet.getRange(2, values[0]['направление'].__col, directs.length, directs[0].length).setValues(directs);
  sheet.getRange(2, values[0]['баланс'].__col, balance.length, balance[0].length).setValues(balance);
}

Преобразование строки в объект

function toCollection_(array) {
  return array.slice(1).map(
    (_, rowIndex) =>
      array[0].reduce((rowCollection, header, columnIndex) => {
        rowCollection[
          String(header)
            .toLowerCase()
            .replace(/[\r\n]+/g, ' ') || `__col${columnIndex}`
        ] = {
          __col: columnIndex + 1,
          __row: rowIndex + 2,
          __val: array[rowIndex + 1][columnIndex],
        };
        return rowCollection;
      }, {}),
    [],
  );
}

Пример данных и рабочий код в Таблице https://docs.google.com/spreadsheets/d/1MqeW7LkEUcsDH8lUksXBLHWmSeu8up2Jr_3ujVwE4SE/edit#gid=1914353719&range=A1