比较两个不同长度的二维数组是否匹配

Comparing two 2D arrays with different length for matches

我试图解决我在为 Google 表格编写小脚本时遇到的问题。我想要做的基本事情是获取整个列的条目并将其与可能具有不同长度的不同 sheet 的另一列的条目进行比较。然后匹配的条目应该被推送到另一个数组,并且在第一个 sheet 的另一列中,每行应该用 "Already in other Spreadsheet" 标记,其中一个匹配条目出现。

第一个 sheet 的第一列包含 5 个元素 [从第 1 行开始] banana apple cucumber strawberry raspberry

第二列中的第二列 sheet 包含 9 个元素 [从第 1 行开始] tomato pineapple strawberry walnut apple watermelon kiwi banana raspberry

这是目前为止的基本代码:

    function arraycompare() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = SpreadsheetApp.getActiveSheet();
  var ss1 = SpreadsheetApp.openById("...Sheet_ID...");
  var sheet1 = ss1.getSheetByName("Sheet1");

  var lastrow = sheet.getLastRow();
  var lastrow1 = sheet1.getLastRow();

  var range = sheet.getRange(1, 1, lastrow, 1);
  var sheetdata = range.getValues();

  var range1 = sheet1.getRange(1, 2, lastrow, 1);
  var sheet1data = range1.getValues();

  var match = [];
for (var x = 0; x < sheetdata.length; x++) {
  for (var y = 0; y < sheetdata[x].length; y++) {
     for(var i = 0; i < sheet1data.length; i++){
       for(var j = 0; j < sheet1data[i].length; j++){
         if (sheetdata[x][y] == sheet1data[i][j]){
           sheet.getRange(x, 2).setValue("Already in other Spreadsheet");
           match.push(sheetdata[x][y]);
         };
       };
     };
  };
};

  //test
  Logger.log(match);

};

记录器的输出只显示 [apple, strawberry] 为匹配项,而不是覆盆子。我假设 for 循环在 5 个元素处停止,但我真的不明白为什么以及如何用 2d 数组解决这个问题?

另外"Already in Spreadsheet"的概念出现在第2行banana和cucumber的行位置,而不是apple和strawberry在同一行。真的很想知道,我在这里做错了什么以及如何解决这个问题以便在这里更好地理解。

希望大家能帮帮我。非常感谢。

我建议进行以下更改:

(1) 由于您使用的是单列数据,因此不需要变量 yj.

sheetdata[x][0] 将是数组第 x 行中字符串的值。

sheet1data[i][0]将是数组第i中字符串的值。

(2) 数组是从零开始的,即数组中的第一个 "row" 是 0。而 sheet 的第一行是 1。

因此,当写入数组中第 x 的 sheet 时,您需要写入第 x+1 sheet.

下面是 for 循环经过这些更改后的样子:

  for (var x = 0; x < sheetdata.length; x++) {
    for(var i = 0; i < sheet1data.length; i++){
      if (sheetdata[x][0] == sheet1data[i][0]){
        sheet1.getRange(x + 1, 2).setValue("Already in other Spreadsheet");
        match.push(sheetdata[x][0]);
      };
    };
  };

正如 Tanaike-san 所说,lastRow1 应该用于计算 range1 而不是 lastRow:

  var range1 = sheet1.getRange(1, 2, lastrow1, 1);

试试这个:

//V8 version
function arraycompare() {
  const ss1=SpreadsheetApp.getActive();
  const sh1=ss1.getSheetByName('Sheet1');
  const rg1=sh1.getRange(1,1,sh1.getLastRow(),1);
  let v1=rg1.getValues().map(function(r){return r[0];});//this flattens the single column 2d array
  const sh3=ss1.getSheetByName('Sheet3');
  sh3.clearContents();
  const ss2id="Spreadsheet 2 id";
  const ss2=SpreadsheetApp.openById(ss2id);
  const sh2=ss2.getSheetByName("Sheet1");
  const rg2=sh2.getRange(1,1,sh2.getLastRow(),1);
  let v3=[['Value','Spreadsheet1 Sheet 1Row','Status','Spreadsheet2Id','Spreadsheet2 Sheet1 Row']];
  let v2=rg2.getValues().map(function(r){return r[0];});
  v1.forEach(function(e,i){
    let idx=v2.indexOf(e);
    if(idx!=-1) {
      v3.push([e,i+1,'Already in other Spreadsheet',ss2id,idx+1]);
    }
  });
  sh3.getRange(1,1,v3.length,v3[0].length).setValues(v3);
} 

//Javascript 1.6 Version
function arraycompare1() {
  var ss1=SpreadsheetApp.getActive();
  var sh1=ss1.getSheetByName('Sheet1');
  var rg1=sh1.getRange(1,1,sh1.getLastRow(),1);
  var v1=rg1.getValues().map(function(r){return r[0];});//this flattens the single column 2d.
  var sh3=ss1.getSheetByName('Sheet3');
  sh3.clearContents();
  var ss2id="Spreadsheet 2 id";
  var ss2=SpreadsheetApp.openById(ss2id);
  var sh2=ss2.getSheetByName("Sheet1");
  var rg2=sh2.getRange(1,1,sh2.getLastRow(),1);
  var v3=[['Value','Spreadsheet1 Sheet 1Row','Status','Spreadsheet2Id','Spreadsheet2 Sheet1 Row']];
  var v2=rg2.getValues().map(function(r){return r[0];});
  v1.forEach(function(e,i){
    var idx=v2.indexOf(e);
    if(idx!=-1) {
      v3.push([e,i+1,'Already in other Spreadsheet',ss2id,idx+1]);
    }
  });
  sh3.getRange(1,1,v3.length,v3[0].length).setValues(v3);
} 

电子表格 1:

banana
apple
cucumber
strawberry
raspberry

电子表格 2:

tomato
pineapple
strawberry
walnut
apple
watermelon
kiwi
banana
raspberry

最终输出

Value,Spreadsheet1 Sheet 1Row,Status,Spreadsheet2Id,Spreadsheet2 Sheet1 Row
banana,1,Already in other Spreadsheet,xxx,8
apple,2,Already in other Spreadsheet,xxx,5
strawberry,4,Already in other Spreadsheet,xxx,3
raspberry,5,Already in other Spreadsheet,xxx,9

您也可以使用 flat and includes:

//simulate `getValues()` column data
const sheet1data = [["banana"],["apple"],["cucumber"],["strawberry"],["raspberry"]];
const sheet2data = [["tomato"],["pineapple"],["strawberry"],["walnut"],["apple"],["watermelon"],["kiwi"],["banana"],["raspberry"]];
const str = "Already in sheet2";
const sheet2_1d = sheet2data.flat();
const out = sheet1data.map(([fruit])=> sheet2_1d.includes(fruit) ? [fruit, str] : [fruit, null]);
console.log(out);//setvalues this out array