簡體   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