繁体   English   中英

有没有更好的方法来根据条件(Google Apps Script)合并行数据?

[英]Is there a better way to merge row data based on criteria (Google Apps Script)?

好的...首先让我说我是自学的 Google Apps 脚本...说的够多了,对吧!? 下面的脚本正在运行,但我想优化它或想出另一种方法来实现相同的结果。 该脚本采用 18000 行和 86 列数据,并根据 id 列表将它们组合成单行。 id 列表大约有 13000 行。 简短的版本是这样的……它按 id 过滤数据,然后检查每一列的最后一行是否有提交的数据并返回该单元格。 例如:

//sample data
[[311112, 1, 2, 4, 5,"","","","","","", 2, 3],
[323223,"","","","","", 2, 4, 4,"","","",""],
[321321, 1, 2, 4, 5,"","","","","","", 2, 3],
[311112, 4, 1, 6, 7,"", 3,"", 3,"","", 5, 3],
[321233,"","","","","","", 4, 3, 1, 5,"",""],
[321321,"","","","","","","","", 1 ,4,"",""],
[323223,"","","","","", 2, 3,"","","","",""],
[323153,"", 2, 3, 6,"","","","","","","",""],
[321321,"","","","","", 2, 3,"","","","",""],
[321321,"", 5, 3,"", 1,"","","","","","",""]]

//filtered Data by id 321321
[[321321, 1, 2, 4, 5,"","","","","","", 2, 3],
[321321,"","","","","","","","", 1, 4,"",""],
[321321,"","","","","", 2, 3,"","","","",""],
[321321,"", 5, 3,"", 1,"","","","","","",""]]

// returned row is getting the last nonempty value for each column from the filtered data.

[[321321, 1, 5, 3, 5, 1, 2, 3,"", 1, 4, 2, 3]]

脚本完成大约需要16-18 分钟 有没有更好的方法来完成这个或任何优化建议?

function combineR(startRow, startRange) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheets = ss.getSheets();
  var testSheet = ss.getSheetByName('Raw Scores');
  var cSheet = ss.getSheetByName('Combined Scores');
  var gradingResults = testSheet.getRange(1, 1, testSheet.getLastRow(), testSheet.getLastColumn()).getValues();

  if (startRow > cSheet.getLastRow()) {
    return;
  }

  if (startRow + startRange > cSheet.getLastRow()) {
    startRange = cSheet.getLastRow() - startRow;
  }

  var sID = cSheet.getRange(startRow, 2, startRange).getValues();
  var maxScores = [];
  for (var x = 0; x < sID.length; x++) {
    var filtered = gradingResults.filter(function (dataRow) {
      return dataRow[0] === sID[x][0];
    });

    if (isFinite(filtered)) {
      maxScores.push(['', '', '', '', '', '', '', '', '', '',
        '', '', '', '', '', '', '', '', '', '',
        '', '', '', '', '', '', '', '', '', '',
        '', '', '', '', '', '', '', '', '', '',
        '', '', '', '', '']);
      continue;
    } else {
      maxScores.push(['', getMaxLetter(filtered, 3), lastGraded(filtered, 4), lastGraded(filtered, 5), lastGraded(filtered, 6), lastGraded(filtered, 7), lastGraded(filtered, 8), lastGraded(filtered, 9), lastGraded(filtered, 10), lastGraded(filtered, 11),
        lastGraded(filtered, 12), lastGraded(filtered, 13), lastGraded(filtered, 14), lastGraded(filtered, 15), lastGraded(filtered, 16), lastGraded(filtered, 17), lastGraded(filtered, 18), lastGraded(filtered, 19), lastGraded(filtered, 20), lastGraded(filtered, 21),
        lastGraded(filtered, 22), lastGraded(filtered, 23), lastGraded(filtered, 24), lastGraded(filtered, 25), lastGraded(filtered, 26), lastGraded(filtered, 27), lastGraded(filtered, 28), lastGraded(filtered, 29), lastGraded(filtered, 30), lastGraded(filtered, 31),
        lastGraded(filtered, 32), lastGraded(filtered, 33), lastGraded(filtered, 34), lastGraded(filtered, 35), lastGraded(filtered, 36), lastGraded(filtered, 37), lastGraded(filtered, 38), lastGraded(filtered, 39), lastGraded(filtered, 40), lastGraded(filtered, 41),
        lastGraded(filtered, 42), lastGraded(filtered, 43), lastGraded(filtered, 44), lastGraded(filtered, 45), lastGraded(filtered, 46)]);
    }
  }
  cSheet.getRange(startRow, 11, maxScores.length, maxScores[0].length).setValues(maxScores)
}

function getMaxLetter(arr, idx) {
  var letter = arr.map(function (e) { return e[idx] }).sort().pop();
  return letter;
}

function lastGraded(arr, idx) {
  var newArray = arr.map(function (e) { return e[idx] });
  newArray.reverse();
  for (var x = 0; x < newArray.length; x++) {
    if (typeof newArray[x] == 'number') {
      return newArray[x];
    }
  }
  return '';
}

A列有重复的ID需要合并原始数据

B 列具有作为最终合并产品的唯一值组合数据

问题:

该脚本似乎有各种问题,但主要问题似乎是使用各种索引多次调用lastGraded函数。 这会为每个索引mapreverse和其他所有内容,并且会花费时间。

解决方案:

鉴于您的样本数据,我建议采用以下方法:

  • 获取 1 个二维数组中的所有输入数据

  • 输入数据减少Map 地图将每个id作为key并将与该key匹配的所有行作为每个key二维array 这将以内存为代价大大提高性能/速度。 这比按每个 id 过滤数组要好,因为,

    • 您只循环输入数组一次
    • arr.filter必须为每个 id 循环数组
  • 一旦缩减为一个map ,对最后一行中的每个元素反向循环遍历map中的每个array以找到非空元素。

示例片段:

 const arrMain = //sample data [ [311112, 1, 2, 4, 5, '', '', '', '', '', '', 2, 3], [323223, '', '', '', '', '', 2, 4, 4, '', '', '', ''], [321321, 1, 2, 4, 5, '', '', '', '', '', '', 2, 3], [311112, 4, 1, 6, 7, '', 3, '', 3, '', '', 5, 3], [321233, '', '', '', '', '', '', 4, 3, 1, 5, '', ''], [321321, '', '', '', '', '', '', '', '', 1, 4, '', ''], [323223, '', '', '', '', '', 2, 3, '', '', '', '', ''], [323153, '', 2, 3, 6, '', '', '', '', '', '', '', ''], [321321, '', '', '', '', '', 2, 3, '', '', '', '', ''], [321321, '', 5, 3, '', 1, '', '', '', '', '', '', ''], ]; //reduce input array to a map of id=>rows const map = arrMain.reduce((map, row) => { if (!map.has(row[0])) map.set(row[0], [row]); else map.get(row[0]).push(row); return map; }, new Map()); const out = []; map.forEach(arr2d => { const l = arr2d.length - 1, lastRow = arr2d[l].slice(0); //iterate lastrow of this id's column elements for (let j = 0; j < lastRow.length; ++j) { if (lastRow[j] === '') { //iterate each row of this id for (let i = l; i >= 0; --i) { if (arr2d[i][j] !== '') { lastRow[j] = arr2d[i][j]; break; } } } } out.push(lastRow); }); console.log(out);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM