首页 > 解决方案 > 使用 map 和 filter 获取与布尔掩码中的“真”值相对应的索引数组

问题描述

我正在处理一个谷歌电子表格,我想在其中执行以下操作:

我有 2 个行范围:“源”和“目标”。在“源”范围内,有 6 个代表骰子的单元格,因此它们的值介于 1 和 6 之间。

我的问题是创建一个函数,该函数基本上将任何值低于某个数字的骰子复制到“dest”范围。

我最初的解决方案是使用copyTo如下循环遍历“源”范围:

function discard_lesser_dice(cutoff_value){
  var ss = SpreadsheetApp.getActiveSpreadsheet()
  var source = ss.getRangeByName('source');
  var dest = ss.getRangeByName('dest');

  for (var i = 1; i <= statusrow.getNumColumns(); i++) {   
    var srccell = source.getCell(1, i);
    if (srccell.getValue() < cuttoff_value)){
      srccell.copyTo(get_next_available_cell(dest));
    }
  }
}

function get_next_available_cell(range){
  for (var i = 1; 1 <= range.getNumColumns(); i++){
    var cell = range.getCell(1, i)
    if (cell.isBlank()){
      return cell
    }
  }
}

这可以完成这项工作,但比我想要的要慢一些,因为.getCell我怀疑的呼叫数量。为了学习更多 Google Apps 脚本/Javascript(我更熟悉 Python/R),我尝试使用mapfilter方法来简化此代码,而不是如下(这似乎确实有效):

function discard_lesser_dice(cutoff_value){ 
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var source = ss.getRangeByName('source');
  var dest = ss.getRangeByName('dest');

  var sourcevals = source.getValues()[0];
  var destvals = dest.getValues()[0];

  // true if value should be discarded
  var mask_source = sourcevals.map((x) => (x < cutoff_value));

  // true if spot is available
  var mask_dest = destvals.map((x) => (x == ''));

  var source_indices = mask_source.map((bool, i) => bool ? i : -1).filter(i => i !== -1);
  var dest_indices = mask_dest.map((bool, i) => bool ? i : -1).filter(i => i !== -1);

  source_indices.forEach((x, i) => source.getCell(1, x+1).copyTo(dest.getCell(1, dest_indices[i]+1)))

}

我的主要问题是,这种方法是否缺少一些在此处使用得更好的工具?

我的主要想法是,在掩码中获取“真实”值的索引数组的方法似乎很老套(即mask.map((bool, i) => bool ? i : -1).filter(i => i !== -1)我在这里找到的)

有没有合适的方法来做到这一点?或者在这种情况下我是否需要这样做并且我错过了解决问题的更明显的方法?如果您不介意提供它,感谢您的帮助。

标签: javascriptarraysgoogle-apps-scriptindexingfilter

解决方案


这是你想要做的:

function movebelowN(n) {
  var n=n||6;
  const ss=SpreadsheetApp.getActive();
  const sh=ss.getActiveSheet();
  const srg=sh.getRange(1,1,1,6);
  const drg=sh.getRange(2,1,1,6);
  let dvs=drg.getValues();
  let svs=srg.getValues();
  svs.forEach(function(d,i){
    d.forEach(function(v,j){
      if(v<n){
        dvs[i][j]=v;
      }else{
        dvs[i][j]='';
      }
    });
  });
  drg.setValues(dvs);
}

推荐阅读