【问题标题】:Why is this comparison between 2 arrays not working, if their contents differ from each other?如果两个数组的内容彼此不同,为什么这两个数组之间的比较不起作用?
【发布时间】:2021-04-19 22:42:14
【问题描述】:

我尝试使用JSON.stringify() 比较两个数组,我尝试在不使用JSON.stringify() 的情况下比较它们,但似乎没有一种方法可以捕捉到数组元素之一的变化。请参阅下面突出显示的内容:

这是我正在运行的一段代码:

    var duplicate = false;
    loop1:
    for (var x = 0; x < data.length; x++) {
      loop2:
      for (var j = 0; j < pushedDbData.length; j++) {
        if (JSON.stringify(data[x].join()) == JSON.stringify(pushedDbData[j].join())) {
          duplicate = true;
          break loop1;
        }
      }
    }
    if (duplicate == true) {
      Browser.msgBox('No change has been been made.');
      return;

感谢您的帮助 - 像往常一样!

【问题讨论】:

  • 数据未定义。请提供minimal reproducible example,这是最小但也是可重复的
  • 您似乎在为某些循环 loop1: 使用此表示法,这不是有效的 javascript。我预计会出现错误,但您似乎正在执行它,所以也许您没有粘贴您正在使用的实际代码?那可能吗?此外,您应该添加一些示例数据,以便可以测试和演示结果。

标签: arrays google-apps-script google-sheets


【解决方案1】:

我了解到,从您的脚本中,datapushedDbData 的数组可能是二维数组。在您的脚本中,当比较datapushedDbData 的数组时,将data 的一个元素与pushedDbData 的所有元素进行比较。此时,当data的元素与pushedDbData的元素之一相同时,duplicate变为true,即使所有其他元素都相同。我认为这可能是您的问题的原因。

为了检查数组的差异,下面2个模式怎么样?

模式一:

在此模式中,datapushedDbData 的数组与相同的索引进行比较。在这种情况下,datapushedDbData 的每个元素都与相同的索引进行比较。示例脚本如下。

var res = data.filter((r, i) => pushedDbData[i] && JSON.stringify(r.join()) != JSON.stringify(pushedDbData[i].join()));
console.log(res)
  • 如果datapushedDbData的每个元素在同一索引下不同,则res的长度大于1

模式2:

在此模式中,datapushedDbData 的数组与所有元素进行比较。在这种情况下,data 的每个元素与pushedDbData 的所有元素进行比较,将相同元素和不同元素作为对象返回。

var obj = data.reduce((o, r, i) => {
  pushedDbData.forEach((s, j) => o[JSON.stringify(s.join()) == JSON.stringify(r.join()) ? "sameElement" : "differentElement"].push({indexOfData: i, indexOfPushedDbData: j}));
  return o;   
}, {sameElement: [], differentElement: []});
console.log(obj)
  • 在此示例脚本中,输出值作为每个数组的索引返回。

注意:

  • 来自but none of the way seems to capture the change in one of the array element. 在您的问题中,我提出了上述两种模式。当我误解了您的目标时,我可以问您您期望的示例输出吗?借此,我想对其进行修改。

参考资料:

补充:

根据您的示例电子表格和当前脚本,如何进行以下修改?

来自

var duplicate = false;
loop1:
for (var x = 0; x < data.length; x++) {
  loop2:
  for (var j = 0; j < pushedDbData.length; j++) {
    console.log(data[x])
    if (data[x].join() == pushedDbData[j].join()) {
      duplicate = true;
      break loop1;
    }
  }
}

收件人:

var obj = data.reduce((o, r) => Object.assign(o, {[JSON.stringify(r.join())]: true}), {});
var duplicate = pushedDbData.every(e => obj[JSON.stringify(e.join())]);
  • 在这个修改后的脚本中,首先从data 创建一个对象,用于从pushedDbData 中搜索值。并且,当data 的值不包含在pushedDbData 中时,将返回true。即使只有一个元素不同,也会返回 false

【讨论】:

  • 您好!与往常一样,您分享精彩内容!尝试保存新添加的数据时出现错误:TypeError: Cannot read property 'join' of undefined 我猜是因为它没有任何可比较的东西,所以它给了我这样的错误。关于根本原因的任何线索?非常感谢!
  • @Antonio Santos 感谢您的回复。我带来的不便表示歉意。从您的错误消息中,我猜您使用的是模式 1。数组 datapushedDbData 的长度可能不同。如果我的理解是正确的,我更新了我的答案。你能确认一下吗?如果我误解了你现在的情况,我再次道歉。届时能否提供datapushedDbData的样本值以及您期望的样本输出?通过这个,我想修改我的答案。
  • 嗨!非常感谢您的宝贵时间。现在,虽然我更改了月份,但在比较时,考虑到模式 1,它显示“没有进行任何更改”。示例如下:docs.google.com/spreadsheets/d/…
  • @Antonio Santos 感谢您的回复。我必须为我的理解不佳道歉。不幸的是,从您的示例电子表格中,我无法理解您期望的输出。您的脚本中有几个函数。您的问题使用saveFixedExpenses()?如果我的理解是正确的,则在您的问题中的脚本中循环使用。而且,data 是字符串值,pushedDbData 是 3 维数组。从这种情况,我可以问你想要的结果吗?通过这个,我想考虑修改点。我再次为我糟糕的英语水平深表歉意。
  • @Antonio Santos 感谢您回复并添加更多信息。根据您的附加信息,我在答案中添加了一个修改后的脚本。你能确认一下吗?如果这不是您期望的结果,我深表歉意。
猜你喜欢
  • 2014-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-12
  • 1970-01-01
  • 2013-04-02
相关资源
最近更新 更多