迭代器的迷雾

Mistery of Iterators

提问人:Gabriele 提问时间:11/14/2023 更新时间:11/14/2023 访问量:61

问:

我为Google Apps Script中迭代器的奇怪行为而疯狂。 我的脚本随机选择一个文件夹(对应于 2012 年和当前年份之间的一年),然后在其中随机选择一个图像。该文件的随机标准是由一个随机整数引导的,该整数在第 1 个迭代时停止循环。 它可以工作,调试和脚本静默执行。但是,但是,但是:脚本的照片滚动渲染始终提供相同的 4-5 张图片。他们是成千上万的人。 我控制缓存,F12 函数选项卡也说缓存为 null,Ctrl+F5 没有任何积极影响。 然后,我要求脚本记录图像的 URL。惊喜:即使输入 if 语句的随机数不同,但生成的 URL 是相同的。碰巧的是,文件夹是相同的,但不同的随机数会选择相同的图像。 帮助!enter image description here

function doGet() {
  var folderImmagini_ID ="myID";
  //---
  // picking year folder between 2012 and current year
  var annoCorrente = new Date().getFullYear();
  var numFolderRandom = Math.random() * (annoCorrente - 2011) + 1;
  var nomeFolderRandom = (numFolderRandom + 2011).toString();
  var nomeFolderFinale = nomeFolderRandom.substring(0, nomeFolderRandom.indexOf("."));
  // once get random folder, picking a random image
  var foldersIterator = DriveApp.getFolderById(folderImmagini_ID).getFolders();
  var nomeCartella, cartella;
  while (foldersIterator.hasNext()) {
    cartella = foldersIterator.next(),
    nomeCartella = cartella.getName();
    if (nomeCartella == nomeFolderFinale) {
      var filesIterator = cartella.getFiles();
      var numeroFiles = 0, file;
      while (filesIterator.hasNext()) {
        numeroFiles = numeroFiles + 1;
        file = filesIterator.next();
      }
      var numFileRandom = Math.floor(Math.random() * numeroFiles) + 1;
      var ordineFile = 0;
      filesIterator = cartella.getFiles();
      while (filesIterator.hasNext()) {
        ordineFile = ordineFile + 1;
        if (ordineFile == numFileRandom) {
          var t = HtmlService.createTemplateFromFile('OutputHTML');
          var foto = filesIterator.next();
          t.fotoID = foto.getId();
                         Logger.log("nome folder: %s, numero random: %s, link foto: %s",nomeCartella, numFileRandom, 
                                    "https://drive.google.com/uc?export=download&id="+ t.fotoID);
          return t.evaluate();
        }
      }
    }   
  }
};
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="0">
  </head>
  <body>
    <center><img src="https://drive.google.com/uc?export=download&id=<?= fotoID ?>" height="85%" width="85%"></center>
  </body>
</html>

javascript google-apps-script 迭代器

评论


答:

1赞 Tanaike 11/14/2023 #1

修改要点:

当我看到您的显示脚本时,似乎在 if 语句中使用了 。在这种情况下,when 为 true,则首次使用。在这种情况下,我担心它不用于选择文件。我认为这可能是您当前问题的原因。var foto = filesIterator.next();if (ordineFile == numFileRandom) {,,,}ordineFile == numFileRandomvar foto = filesIterator.next();ordineFile = ordineFile + 1;

如果你想修改你的放映脚本,下面修改怎么样?

从:

while (filesIterator.hasNext()) {
  ordineFile = ordineFile + 1;
  if (ordineFile == numFileRandom) {
    var t = HtmlService.createTemplateFromFile('OutputHTML');
    var foto = filesIterator.next(); // <--- here
    t.fotoID = foto.getId();
    Logger.log("nome folder: %s, numero random: %s, link foto: %s", nomeCartella, numFileRandom,
      "https://drive.google.com/uc?export=download&id=" + t.fotoID);
    return t.evaluate();
  }
}

自:

while (filesIterator.hasNext()) {
  ordineFile = ordineFile + 1;
  var foto = filesIterator.next(); // <--- here
  if (ordineFile == numFileRandom) {
    var t = HtmlService.createTemplateFromFile('OutputHTML');
    t.fotoID = foto.getId();
    Logger.log("nome folder: %s, numero random: %s, link foto: %s", nomeCartella, numFileRandom,
      "https://drive.google.com/uc?export=download&id=" + t.fotoID);
    return t.evaluate();
  }
}
  • 在本例中,被移到了 的 if 语句之外。var foto = filesIterator.next();if (ordineFile == numFileRandom) {,,,}

注意:

  • 作为另一种方法,我认为文件是从文件 ID 列表中随机选择的。在这种情况下,以下修改怎么样?

    function doGet() {
      var folderImmagini_ID = "myID";
      //---
      // picking year folder between 2012 and current year
      var annoCorrente = new Date().getFullYear();
      var numFolderRandom = Math.random() * (annoCorrente - 2011) + 1;
      var nomeFolderRandom = (numFolderRandom + 2011).toString();
      var nomeFolderFinale = nomeFolderRandom.substring(0, nomeFolderRandom.indexOf("."));
      // once get random folder, picking a random image
      var foldersIterator = DriveApp.getFolderById(folderImmagini_ID).getFolders();
      var nomeCartella, cartella;
    
      // I modified the below script.
      while (foldersIterator.hasNext()) {
        cartella = foldersIterator.next(), nomeCartella = cartella.getName();
        if (nomeCartella == nomeFolderFinale) {
          var filesIterator = cartella.getFiles();
          var fileIds = [];
          while (filesIterator.hasNext()) {
            fileIds.push(filesIterator.next().getId());
          }
          var numFileRandom = Math.floor(Math.random() * fileIds.length);
          var t = HtmlService.createTemplateFromFile('OutputHTML');
          t.fotoID = fileIds[numFileRandom];
          Logger.log("nome folder: %s, numero random: %s, link foto: %s", nomeCartella, numFileRandom + 1, "https://drive.google.com/uc?export=download&id=" + t.fotoID);
          return t.evaluate();
        }
      }
    }
    

评论

0赞 Gabriele 11/14/2023
我将尝试使用 next() 迭代文件的“提取”脚本。
0赞 Gabriele 11/14/2023
关于随机选择一个 ID,这确实是一个优雅的解决方案,我怀疑它在机器时间方面要快一点。
0赞 Gabriele 11/14/2023
“我将尝试使用 next() 迭代文件的”提取“脚本。” 续: 然而,我担心如果它成功了,那将是由于编译例程,因为从算法的角度来看,next() 的位置似乎是严格的地方。
0赞 Tanaike 11/14/2023
感谢您的回复。如果我的回答没有用,我深表歉意。关于,我也认为这是肯定的。关于,我无法理解。我为我糟糕的英语水平道歉。About randomly selecting an ID, it is truly an elegant solution, and I suspect it is a little bit faster in terms of machine-time.However, I am afraid that if it successed it would due to the compilation routine, since from a alghoritmic point of view the place of the next() seems to be the rigth place.
0赞 Gabriele 11/14/2023
我不知道你的英语是差还是比我的好,但你在 .next() 语句的位置上是正确的。底线:它终于起作用了。