【问题标题】:looping through arrays at different rates以不同的速率循环遍历数组
【发布时间】:2014-12-31 02:25:33
【问题描述】:

filesNamed 是我想要累积和设置数据的参考数组。因此,对于filesNamed 中的每个索引,应累积来自emailData 的包含相同电影标题的数组,并最终将其设置在谷歌电子表格中的一个范围内。将数据设置在一个范围之外,我在这个任务的第一部分遇到了问题。

var filesNamed = [
                  ["Happiness","Karate for Life","Dogtooth","The Streetfighter","Mind Game","The Raid","The Hole","Plaga Zombie","Funny Games"]
                ];

var emailData = [
                      ["Date","Happiness","Sender 1","Receiver 1","Subject 1" ],
                      ["Date","Happiness","Sender 1","Receiver 1","Subject 1" ],
                      ["Date","Happiness","Sender 1","Receiver 1","Subject 1" ],
                      ["Date","Happiness","Sender 1","Receiver 1","Subject 1" ],
                      ["Date","Happiness","Sender 1","Receiver 1","Subject 1" ],
                      ["Date","Karate for Life","Sender 2","Receiver 2","Subject 2" ],
                      ["Date","Karate for Life","Sender 2","Receiver 2","Subject 2" ],
                      ["Date","Karate for Life","Sender 2","Receiver 2","Subject 2" ],
                      ["Date","Karate for Life","Sender 2","Receiver 2","Subject 2" ],
                      ["Date","Karate for Life","Sender 2","Receiver 2","Subject 2" ],
                      ["Date","Karate for Life","Sender 2","Receiver 2","Subject 2" ],
                      ["Date","Dogtooth","Sender 3","Receiver 3","Subject 3" ],
                      ["Date","Dogtooth","Sender 3","Receiver 3","Subject 3" ],
                      ["Date","Dogtooth","Sender 3","Receiver 3","Subject 3" ],
                      ["Date","Dogtooth","Sender 3","Receiver 3","Subject 3" ],
                      ["Date","The Streetfighter","Sender 4","Receiver 4","Subject 4" ],
                      ["Date","The Streetfighter","Sender 4","Receiver 4","Subject 4" ],
                      ["Date","The Streetfighter","Sender 4","Receiver 4","Subject 4" ],
                      ["Date","The Streetfighter","Sender 4","Receiver 4","Subject 4" ],
                      ["Date","Mind Game","Sender 5","Receiver 5","Subject 5" ],
                      ["Date","Mind Game","Sender 5","Receiver 5","Subject 5" ],
                      ["Date","Mind Game","Sender 5","Receiver 5","Subject 5" ],
                      ["Date","Mind Game","Sender 5","Receiver 5","Subject 5" ],
                      ["Date","The Raid","Sender 15","Receiver 15","Subject 15" ],
                      ["Date","The Raid","Sender 15","Receiver 15","Subject 15" ],
                      ["Date","The Raid","Sender 15","Receiver 15","Subject 15" ],
                      ["Date","The Raid","Sender 15","Receiver 15","Subject 15" ],
                      ["Date","The Hole","Sender 25","Receiver 25","Subject 25" ],
                      ["Date","The Hole","Sender 25","Receiver 25","Subject 25" ],
                      ["Date","The Hole","Sender 25","Receiver 25","Subject 25" ],
                      ["Date","Plaga Zombie","Sender 35","Receiver 35","Subject 35" ],
                      ["Date","Plaga Zombie","Sender 35","Receiver 35","Subject 35" ],
                      ["Date","Plaga Zombie","Sender 35","Receiver 35","Subject 35" ],
                      ["Date","Funny Games","Sender 45","Receiver 45","Subject 45" ],
                      ["Date","Funny Games","Sender 45","Receiver 45","Subject 45" ]
                   ];

下面代码的问题在于,虽然第一次循环通过 filesNamed[0][0] == emailData[0][1] 返回匹配,但第二次循环,两个 for 循环都递增 - 但我们还没有完成从 emailData 累加所有数组上面的标题Happiness(还有4个)。我认为计数器应该只在循环中断后增加,这表明我们已经到达了属于移动幸福的数组的最后一个。我尝试将 counter(l++) 放在 else 语句中,但这不起作用。

正如我所说的那样:我希望数组中属于特定电影标题的所有数据都放在它自己的电子表格中。每个子数组(以日期开头)应该在自己的行中,其中索引将跨越 5 列。

function theo (){

  Logger.log("emailData.length: " + emailData.length);
  Logger.log("filesNamed[0].length: " + filesNamed[0].length);
  for(var i=0;i<emailData.length;i++){
    for(var l=0;l<filesNamed[0].length;l++){
      if(filesNamed[0][l] == emailData[i][1]){
        Logger.log("");
        Logger.log("match");
        Logger.log("emailData[0]): " + emailData[i][1]);
        Logger.log("filesNamed[0][l]: " + filesNamed[0][l]);
        Logger.log("");
        Logger.log("l: "+l);
        Logger.log("i: "+i);
      } else {
        Logger.log("");
        Logger.log("broke");
        Logger.log("emailData[0]): " + emailData[i][1]);
        Logger.log("filesNamed[0][l]: " + filesNamed[0][l]);
        Logger.log("");
        Logger.log("l: "+l);
        Logger.log("i: "+i);
      }
    }
  }
}

Happiness 电子表格将包含 5 行。 Karate for Life 电子表格将包含 6 行。 Dogtooth 电子表格将包含 4 行。等等……

一位朋友建议我学习迭代器,我会的,但我想知道是否有另一种方法来构建我的双循环,以便更接近原始方法的工作。还有一些教训可以摆脱这种失败。

【问题讨论】:

  • 除了将日志记录为调试方法之外,您希望从这些循环中输出什么?你说累积的电子邮件数组,但不清楚你想要什么或为什么你有什么不起作用。
  • 我在两个代码 sn-ps 之间解释了为什么这不起作用。这个想法是将属于特定电影标题的所有数组设置为具有相同电影标题的特定谷歌电子表格的行。这个列表会不断积累新的片名,每个片名都会不断积累数组。
  • 恐怕我没有遇到问题。运行theo 每次递增emailData 时都会循环通过filesNamed,但具体到filesNamed 的链接是什么?您希望 emailData 中的所有数组都是单独的行还是每个标题连接?
  • 从您的问题编辑中,我认为您已经得到了您想要的,但不是您期望的。交换循环,你会看到相同的匹配,但顺序不同。

标签: javascript arrays for-loop google-apps-script


【解决方案1】:

我认为您正在寻找的最简单的积累可以是这样的。

function theo2() {
  var accumulatedFiles = filesNamed[0].map(
    function (title) {
      var emails = this;
      return {
        title: title,
        emails: emails.filter(
          function (email) {
            var title = this;
            return email[1] == title;
          },
          title
        )
      };
    },
    emailData
  );
}

这会产生一个对象数组,其中第一个索引是filesNamed 中的电影标题索引,标题属性是标题,电子邮件属性是该索引内的数组数组与标题匹配的数组。

副产品是它只返回标题与原始来源列表匹配的电子邮件。如果您希望通过电子邮件回复来确定标题累积并且根本没有 filesNamed 数组,您可以更加紧凑。

这将是一个开始,您可以使用它来填充工作表或任何您想做的事情。

正如 Sandy 指出的那样,上面的函数放弃使用循环,而是使用 .map().filter()。循环也可以,但我个人更喜欢语义描述和方法的简洁性。

为了完整起见,循环形式可能是这样(猜猜看,这或多或少是你已经拥有的):

function theo3() {
  var accumulatedFiles = [],
      filmEmails = [];

  for (var i = 0; i < filesNamed[0].length; i += 1) {    
    filmEmails = [];
    for (var j = 0; j < emailData.length; j += 1) {
      if (emailData[j][1] == filesNamed[0][i]) {
        filmEmails.push(emailData[j]);
      }
    }
    accumulatedFiles.push({title: filesNamed[0][i], emails: filmEmails});
  }
}

【讨论】:

  • 一些方法链接:map Method 和:filter Method
  • 并非所有浏览器都支持它们,但 Google Apps 脚本完全支持它们——尽管如果您在其中添加断点,IDE 调试器会中断。
【解决方案2】:

您想知道电影名称是否匹配。你可以通过indexOf()判断一个数组是否有某个元素。

var isItA_Match = filesNamed.indexOf("Happiness");

如果在“filesNamed”数组中的任何位置找到单词“Happiness”,则将索引号分配给变量“isItA_Match”。如果没有匹配,则返回值 -1。

此代码不完整或不正确,但希望您了解我尝试使用的逻辑:

function theo() {

  Logger.log("emailData.length: " + emailData.length);
  Logger.log("filesNamed[0].length: " + filesNamed[0].length);

  var happinessArray = [];
  var karateArray = [];

  //Create all the arrays for each movie Title
  for(var i=0;i<emailData.length;i++) {

    var elmtToMatch = emailData[i][1];
    var isItA_Match = filesNamed.indexOf(elmtToMatch);

    if (isItA_Match > -1) {
      Logger.log("match");
      //put data into correct Array
      if (matchCorrectArray) {
         happinessArray = data;
      }
    };
  };
};

使用indexOf() 检查数组中的每个元素。您不需要遍历每个元素来查找匹配项。这样就避免了需要循环。

一旦您获得了包含正确数据的所有数组,您就可以调用另一个函数,然后将数据写入每个相应的电子表格。创建一个将电影名称与电子表格 ID 匹配的对象。

创建将电影名称与电子表格 ID 匹配的对象

var objMovieToSheetID = {"Happiness":"48rjdjfoierawj", "Karate for Life":"894ilkdjfhwo"};

创建一个匹配电影名称和数组名称的对象

var objMovieToArrayName = {"Happiness":"Hap", "Karate for Life":"Kar"};

调用函数循环打开每个电子表格的过程

function addDataToSheets() {

  //An object that matches the movie title to the spreadsheet ID
  var objMovieToSheetID = {"Happiness":"48rjdjfoierawj", "Karate for Life":"894ilkdjfhwo"};

  var objMovieToArrayName = {"Happiness":"Hap", "Karate for Life":"Kar"};

  //Loop through all the movie titles and add data to each spreadsheet
  for(var i=0; i<objSheetToArrayName.length; i++){

    // The code below opens a spreadsheet using its ID and logs the name for it.
    // Note that the spreadsheet is NOT physically opened on the client side.
    // It is opened on the server only (for modification by the script).

    //get each movie name from the array in sequence by index
    var movieName = filesNamed[i];
    //Retrieve the spreadsheet ID from the object that matches movie name to spreadsheet ID
    var ssID = objSheetToArrayName[movieName];
    var ss = SpreadsheetApp.openById(ssID);
    Logger.log(ss.getName());

    var dataToAppend = emailData[objMovieToArrayName[movieName]];
    // Appends a new row with to the bottom of the
    // spreadsheet containing the values in the array
    sheet.appendRow(dataToAppend);
  };

};

【讨论】:

  • 我也是这么想的,但它的积累细节我不清楚mrcni想要什么。每个电影标题单独的文件,单独的表等?
  • 好吧,最坏的情况是我有机会投反对票。 ;) 有时我回答是希望最好的。
  • 我希望属于特定电影标题的所有数据都放入他们自己的电子表格中。每个子数组应该在自己的行上,其中的索引将跨越 5 列。
  • 我会创建一个对象,将每个电影名称与您希望存储数据的工作表的电子表格 ID 相匹配。我更新了我的答案。我还没有编写出所有数组的代码,但希望你能看到我的目标。
猜你喜欢
  • 2016-12-22
  • 2015-02-22
  • 2015-05-19
  • 2021-10-08
  • 2019-08-11
  • 2015-10-13
  • 1970-01-01
  • 2014-06-04
相关资源
最近更新 更多