【问题标题】:Checking to see if a value exists anywhere in an array检查一个值是否存在于数组中的任何位置
【发布时间】:2018-05-12 06:23:25
【问题描述】:

我有一个脚本,它查看一个工作表(“数据”)并从一列日期中找到未来 3 个月的日期,并将这些行复制到另一个工作表(“3 个月”)中。它可以做到,耶!

我还希望它在“3 个月”表上检查每一行的唯一 ID,如果该唯一 ID 存在,则不要从“数据”复制该行。

它会这样做,但前提是“3 Months”中的数据与“Data”中的数据顺序相同,否则不会。显然,它所做的是将当前唯一 ID 与数组中的等效唯一 ID 匹配。而不是尝试将当前唯一 ID 与数组中的所有 ID 匹配,并确保它不匹配其中任何一个。

这就是我所拥有的:

function contractSearch2() {
  //Get all the sheet names as variables
  var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data");
  var threeMonths = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("3 Months");

  //Get all the expiry dates on the data sheet
  var lastRow = dataSheet.getLastRow();
  var endDates = dataSheet.getRange(1, 11, lastRow).getValues();

  //Get today's date
  var today = new Date();

  // Work out when 3 months from now is.
  var threeMonthsOut = new Date(today);
  var CurrentDate = new Date();
  threeMonthsOut.setMonth(CurrentDate.getMonth() + 3);

  // Find months / years that match 3 months out.
  var threeMonthslastRow = threeMonths.getLastRow();
  var CallOffIDs = threeMonths.getRange(1, 4, threeMonthslastRow+1, 1).getValues();
  var test = 0
  var j = 0; 
  //Logger.log(CallOffIDs[1])

  for (var i = 0; i < endDates.length; i++){
    var fDate = new Date(endDates[i][0]);
    // if a date is 3 months in the future
    if (fDate.getMonth() == threeMonthsOut.getMonth() && 
        fDate.getFullYear() == threeMonthsOut.getFullYear()) {
      //get all the row info
      var entry = dataSheet.getRange(i+1, 1, 1, 44).getValues();

      // Check to see if CallOff ID Exists already
      // Get the CallOff ID from the entry row
      var CallOffCheck = entry[0][3];
      ++j;
      for ( test in CallOffIDs) {
        ++test;
        if (CallOffCheck == CallOffIDs[j]) {
          break;
        } else {
          var threeMonthslastRow2 = threeMonths.getLastRow(); 
          threeMonths.getRange(threeMonthslastRow2 + 1, 1, 1, 44).setValues(entry);
          break;  
        }
      }  
    }
  }
}

由于另一个原因我需要对“3 个月”上的行重新排序,并且“数据”表上的数据总是在更新,所以我需要不断地运行脚本。这就是为什么我需要它来检查所有值。

提前致谢。

【问题讨论】:

  • 如果您有很多行要与每一行进行比较,请考虑对对象中的唯一 ID 进行散列处理,因为您只需检查该对象属性是否存在。例如,查看我最近的回答:stackoverflow.com/a/50286994/9337071
  • 嘿,丹。你到底在哪里搜索?我似乎无法理解您的代码。此外,就像上面提到的 tehhowch,如果它是一个大数组,请考虑创建一个唯一的 ID 映射以帮助加快搜索查找速度。
  • 您的检查循环中确实出现了一些奇怪的索引模式,以及一些未使用的变量。我建议重写方法,首先用伪代码写在纸上,这样你就可以在实施之前获得详细信息。

标签: javascript google-apps-script


【解决方案1】:

数组提供四种搜索方式:

  • someArray.some - 根据是否找到项目返回真或假。让您编写一个函数来进行比较/匹配。此方法在 Google Apps 脚本中可用。
  • someArray.find - 从数组中返回一个元素并让您编写一个函数来进行比较/匹配。如果存在多个匹配元素,则仅返回第一个。此方法在 Google Apps 脚本中可用。
  • someArray.findIndex - 从数组中返回元素的索引,并让您编写一个函数来进行比较/匹配。如果存在多个匹配元素,则仅返回第一个。此方法在 Google Apps 脚本中可用。
  • someArray.indexOf - 如果未找到匹配项,则返回 -1,否则返回匹配元素的基于 0 的索引。您必须传递一个值来搜索,并且还可以传递数组的位置,从该位置成为搜索循环。此方法在 Google Apps 脚本中可用。

var beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];

    console.log(beasts.indexOf('bison'));
    // expected output: 1
    
    // start from index 2
    console.log(beasts.indexOf('bison', 2));
    // expected output: 4
    
    console.log(beasts.indexOf('giraffe'));
    // expected output: -1
    
    var foundItem = beasts.find(function(item, arr, index) {
       return item === 'camel'; // my function is searching for camel
    });
    console.log(foundItem);
    // expected output: 'camel'
    
    
    var foundItemIndex = beasts.findIndex(function(item, arr, index) {
       return item === 'camel'; // my function is searching for camel
    });
    console.log(foundItemIndex);
    // expected output: 2

我希望这会有所帮助。

【讨论】:

  • 遗憾的是 Google Apps 脚本 (GAS) 不支持 Array::find()Array::findIndex(); GAS 不是完整的 ES6 实现。众所周知,Array::indexOf() 在某些情况下在 GAS 中存在问题。但是,GAS 确实支持Array::some()。您可以重构您的答案以改用该方法。
  • 好的,谢谢。我很欣赏你的回应。我理解这是如何工作的,但它只会返回-1,我认为是因为我的数组是 2d。有什么想法可以解决这个问题吗?
  • 你可以简单地使用 .join().split(); 来“扁平化”你的数组。这将创建一个一维数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
  • 2022-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-20
相关资源
最近更新 更多