【问题标题】:How do I remove null values from an array within an array?如何从数组中的数组中删除空值?
【发布时间】:2019-09-11 18:25:39
【问题描述】:

我正在使用 Google 表格和 Google Apps 脚本。我使用.getRange().getValues 从工作表中获取用户电子邮件。

收到的示例数组: [[user1, , ], [user2, user3, ], [user4, user5, user6]]

如您所见,我有可能每行最多三个用户(内部数组)。但是,其中一些单元格是空的,导致数组中的值为空。然后我将每个内部数组输入.addEditors(),由于用户为空而引发错误。

我知道我可以遍历每个数组并删除空数组,然后将新数组推送到.addEditors(),但这会很丑陋,而且效率很低。我没有足够的经验知道如何开发更优雅的方式。

有人可以帮助我了解以尽可能有效的方式解决此问题的方式和原因吗?谢谢。

注意:虽然.filter(Boolean) 解决方案似乎可行,但我只能让它适用于单个数组,而不适用于数组中的数组。

var myFilterArray = myArray.filter(Boolean);

    arr.forEach(function(x){
      return x.filter(Boolean);
    });

如果深度大于一,我无法让它返回修改后的数组。

【问题讨论】:

  • 我检查过了,但无法让该解决方案发挥作用。收集的值似乎是虚假的,而是被视为 0。尽管如此,这将是最简单的解决方案。

标签: javascript arrays google-apps-script multidimensional-array google-sheets


【解决方案1】:

出于好奇,我在 3 列和 1000 行数据上分别运行了这四个函数 10 次。部分地,我有兴趣了解更多关于这些数组方法的信息,因为我刚刚开始使用它们。所以我肯定不是他们的专家。

代码:

function removeFalsies1() {
  var start=new Date();
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getActiveSheet();
  var rg=sh.getDataRange();
  var vA=rg.getValues();
  var vU=[];
  var cnt=0;
  for(var i=1;i<vA.length;i++){
    for(var j=0;j<vA[i].length;j++) {
      cnt++;
      if(vA[i][j]) {
        vU.push(vA[i][j]);
      }
    }
  }
  var end=new Date();
  return Utilities.formatString('1,%s',seconds_(start,end));
}

function removeFalsies2() {
  var start=new Date();
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getActiveSheet();
  var rg=sh.getDataRange();
  var vA=rg.getValues();
  var cnt=0;
  var vU=[];
  vA.forEach(function(r,i,A){ 
    if(i>0) {
      for(var n=0;n<A[i].length;n++){
        var rA=[];
        cnt++;
        if(A[i][n] && i>0){
          vU.push(A[i][n]);
        }
      }
    }
    return rA;
  });
  var end=new Date();
  return Utilities.formatString('2,%s',seconds_(start,end));
}

function removeFalsies3() {
  var start=new Date();
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getActiveSheet();
  var rg=sh.getDataRange();
  var vA=rg.getValues();
  var cnt=0;
  var vU=[];
  vA.forEach(function(r,i,A){if(i>0){r.forEach(function(rix,ix,r){if(rix){vU.push(rix);}cnt++;})}});
  var end=new Date();
  return Utilities.formatString('3,%s',seconds_(start,end));
}

function removeFalsies4() {
  var start=new Date();
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getActiveSheet();
  var rg=sh.getDataRange();
  var vA=rg.getValues();
  var cnt=0;
  var vU=[];
  vA.map(function(r,i) {if(i>0){return r.filter(function(rix){if(rix){vU.push(rix);}cnt++;})}});
  var end=new Date();
  return Utilities.formatString('4,%s',seconds_(start,end));
}

数据:

单个数字是指函数名称中的最后一个数字。

【讨论】:

    【解决方案2】:

    我知道我可以遍历每个数组并删除空对象...这几乎是您唯一的选择。有一些方法可以让你的代码看起来更干净,但在幕后需要循环遍历数组。

    这是一个使用Array.map()Array.filter() 的示例

    let data = [["bob", , ], ["jake", "john", ""], ["joe", "henry", "morgan"]];
    let newData = data.map(x => {
      return x.filter(j => j)
    })
    console.log(newData);

    使用 ES5 语法

    var data = [["bob", , ], ["jake", "john", ""], ["joe", "henry", "morgan"]];
    var newData = data.map(function(x) {
      return x.filter(function(j) {if (j) return j})
    })
    console.log(newData);

    【讨论】:

    • 如果知道不需要的(空)槽总是在数组的末端,可以通过设置.length来简单地截断数组。
    • @Isaac - 这看起来正是我需要的代码。但是,我试图在您编写它时只运行此代码,但我在第二行不断收到错误消息。它告诉我我需要一个分号。你能帮我理解这段代码是如何工作的,以便我可以将它放入应用程序脚本中而不会出现错误吗?
    • 可能是因为您的浏览器不支持数组函数语法,或者因为您没有将 es5 转换为 es6。尝试使用 es5 语法。
    • 完美!是的,这是语法。因此,在试图理解....map 创建数组的副本,.filter 仅保留那些具有值的元素。 if (j) return j 是如何工作的?它只是说“因为有一个值,所以返回那个值?”
    【解决方案3】:

    如果您有以下类型的数组,那么我们可以使用过滤方法去除空数据。

    var data=[["user1", , ], ["user2", "user3", ], ["user4", "user5", "user6"]];
    
    data.filter(a => a.filter( b => b.length>0));
    

    【讨论】:

    • 谢谢,但我无法让此代码在应用程序脚本 IDE 中运行。
    • 我意识到这里的问题是您的代码是 ES6 语法,而我使用的是 ES5。感谢您的帮助。
    猜你喜欢
    • 2019-09-05
    • 2020-01-01
    • 2021-04-10
    • 1970-01-01
    • 2017-03-16
    • 1970-01-01
    相关资源
    最近更新 更多