VLookup 的 Google 脚本版本(更有效的方法?)

Dan*_*Cue 2 google-sheets google-apps-script google-sheets-formula

我正在尝试组合一个函数,该函数允许我根据关键列将列的信息从一张纸拉到另一张纸上。这与 excel/google 中的索引匹配或 vlookup 类似。

样本数据:

在此输入图像描述

我尝试过的:

function vlookup(importFromSht, importToSht, importFromCompCol, importToCompCol,importFromCol, importToCol){
  var lastImportFromRN = importFromSht.getLastRow();
  var lastImportToRN = importToSht.getLastRow();
  var importFromCompArr =  importFromSht.getRange(2, importFromCompCol, lastImportFromRN, 1).getValues();
  var importToCompArr =  importToSht.getRange(2, importToCompCol, lastImportToRN, 1).getValues();
  var importFromArr =  importFromSht.getRange(2, importFromCol, lastImportFromRN, 1).getValues();
  var importToArr = [];

  for (var i in importToCompArr) {
    for (var j in importFromCompArr){
      if (importToCompArr[i].toString() == importFromCompArr[j].toString()) { 
        importToArr.push(importFromArr[j]);
      }
    }
  }

  //Paste to column
  importToSht.getRange(2,importToCol,importToArr.length,1).setValues(importToArr);
}
Run Code Online (Sandbox Code Playgroud)

参数定义

  • importFromSht - 我们正在从中获取值的表。
  • importToSht - 工作表值将被复制到。
  • importFromCompCol - 具有要匹配的值的列(数字)。
  • importToCompCol - 具有要匹配的值的列(数字)。
  • importFromCol - 包含需要复制的值的列(数字)。
  • importToCol - 要将值复制到的列(编号)。

要求:

  • 最少有超过 6K 行,可能有数千行。执行速度很重要。我的方法是正确的方法还是有更有效的方法?我的脚本使执行时间增加了大约 30 秒。
  • 想要将其称为函数,因为我可以看到自己在该项目和其他项目的其他领域中使用它。

The*_*ter 5

问题:

  • 慢速脚本:
    • O(n 2 ):对于数组 1 中的每个元素,从上到下迭代数组 2。即使在数组 2 中找到匹配项后,循环也不会中断(break),但内部循环会不必要地完成,直到数组 2 末尾。

    • getValues() 对于同一张纸的两列,请求两次。接触电子表格的成本很高。所以,限制它是必要的。

解决方案:

一种可能实现的解决方案O(n):

  • 使用数组 1 创建一个新对象,并将键作为“要查找的值”。然后对于数组 2 中的每个值,每次都可以直接访问该对象中的值。

示例脚本:

const ss = SpreadsheetApp.getActive();
/**
 * @param {GoogleAppsScript.Spreadsheet.Sheet} fromSht -Sheet to import from
 * @param {GoogleAppsScript.Spreadsheet.Sheet} toSht -Sheet to import to
 * @param {Number} fromCompCol -Column number of fromSht to compare
 * @param {Number} toCompCol -Column number of toSht to compare
 * @param {Number} fromCol -Column number of fromSht to get result
 * @param {Number} toCol -Column number of toSht to get result
 * @author /sf/users/588311741/
 */
function vlookup_custom(
  fromSht = ss.getSheetByName('Sheet1'),
  toSht = ss.getSheetByName('Sheet2'),
  fromCompCol = 1,
  toCompCol = 1,
  fromCol = 2,
  toCol = 2
) {
  const toShtLr = toSht.getLastRow();
  const toCompArr = toSht.getRange(2, toCompCol, toShtLr - 1, 1).getValues();
  const fromArr = fromSht.getDataRange().getValues();
  fromCompCol--;
  fromCol--;

  /*Create a hash object of fromSheet*/
  const obj1 = fromArr.reduce((obj, row) => {
    let el = row[fromCompCol];
    el in obj ? null : (obj[el] = row[fromCol]);
    return obj;
  }, {});

  //Paste to column
  toSht
    .getRange(2, toCol, toShtLr - 1, 1)
    .setValues(toCompArr.map(row => (row[0] in obj1 ? [obj1[row[0]]] : [null])));
}

Run Code Online (Sandbox Code Playgroud)

表现:

  • 工作表 1 中的 10000 行和工作表 2 中的 10000 行大约需要 5 秒

参考: