为什么我在 Google 脚本中对看似完全相同的输入执行 indexOf 操作会得到不一致的结果?
Why do I get inconsistent results from an indexOf action in Google Scripts on what appear to be the exact same inputs?
我试图找到一种在 Google 脚本中搜索数组的方法,但一直找不到任何可行的方法。我的最终目标是对 Google Sheet 中的多个数组进行 vlookup,对它们执行函数,然后将它们推入另一个数组以进行粘贴以供分析。我需要执行大约 2,500 个循环,因此我尽量避免 reading/writing。这是我的主要障碍的一个极其简单的版本。
当我在一个数组中查找数字的索引时,除了 -1 之外我无法得到任何其他内容,除非我正在查找该数组的一个子集。当我寻找不同数组的精确副本或对它进行硬编码时,我得不到一致的结果。预先感谢您的帮助和耐心等待!
这是我 spreadsheet 的 link,这里有一张图片供快速参考:
这是我尝试使用的代码,表明我得到了不同的索引,我认为应该是相同的结果:
function indexOfTest() {
//Set sheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName("Data");
//Get ranges
var dataRange = dataSheet.getRange("A1:B7").getValues(); //data set of the locations I want to search eventually
var findRange = dataSheet.getRange("E3:E4").getValues(); //values I want to find the row of in the data set (would change in the spreadsheet based on the user's inputs)
var locationRange = dataSheet.getRange(1,1,dataSheet.getLastRow()).getValues(); //smaller range of the locations I want to locate (1st column)
//test showing that indexOf works when I search for a subset of the array within the array
var findTest1 = locationRange[2]; //set variable to a subset of the array I will search
var searchResult1 = locationRange.indexOf(findTest1); //finding the index of the subset of the array within the array
//test showing that indexOf does NOT work when I search for the exact same value in the same array
var findTest2 = findRange[0]; //set variable to the the user-entered cell on the sheet which is exactly the same as the subset of the array from the first test
var searchResult2 = locationRange.indexOf(findTest2); //this comes back as -1 for some reason
//test showing that I can't even find it when I hard code it to exactly the same as somethng in the array that I was able to find earlier
var findTest3 = [13]; //hardcoded variable to exactly the same as the subset of the array from the first test
var searchResult3 = locationRange.indexOf(findTest3); //this comes back as -1 for some reason
var x = 1 // this is where I have the debug spot (x = 1 is meaningless but wanted the debugger to stop here)
// why does the indexOf function work for the first test but not the other two?!?!?!?
// any help would be greatly appreciated! thanks!
}
当我查看调试器时,我不明白为什么我在两个测试中得到 -1 但它在一个测试中有效...而且他们正在搜索完全相同的东西!
拜托了,非常感谢!
这个答案怎么样?
getValues()
检索到的值是二维数组。
对于您的情况,这是非常重要的一点。
1。准备
作为准备,它确认了dataRange
、findRange
、locationRange
、findTest1
、findTest2
和findTest3
的值。
检索到dataRange
、findRange
、locationRange
时,如下
dataRange = [["Location #","State"],[11,"AK"],[13,"NE"],[17,"FL"],[24,"IL"],[47,"IL"],[69,"NV"]]
findRange = [[13],["State"]]
locationRange = [["Location #"],[11],[13],[17],[24],[47],[69]]
和findTest1
、findTest2
和findTest3
是[13]
。
2。实验
在这里,它想到了使用 findTest1
、findTest2
和 findTest3
进行搜索的大约 3 种模式。
模式 1
var findTest1 = locationRange[2];
var searchResult1 = locationRange.indexOf(findTest1);
在这种情况下,from [13]
是从 [["Location #"],[11],[13],[17],[24],[47],[69]]
开始搜索的,即 locationRange
。但是 findTest1
在 locationRange
中。这行得通。我认为是因为 indexOf()
可能会使用同一数组中的元素引用来自同一数组的指针。作为另一个示例,请参阅以下示例脚本。
var ar = [[1, 2, 3], [4, 5, 6], [4, 5, 6], [7, 8, 9]];
var r1 = ar.indexOf([4, 5, 6]); // -1
var r2 = ar.indexOf(ar[2]); // 2
在这个脚本中,indexOf()
可以使用同一个二维数组中的元素。在Array.prototype.indexOf()
处,当查找的值是一个数组时,可能会引用指针。这个结果对我来说是新发现。
模式 2
var findTest2 = findRange[0];
var searchResult2 = locationRange.indexOf(findTest2);
在这种情况下,from [13]
是从 [["Location #"],[11],[13],[17],[24],[47],[69]]
开始搜索的,即 locationRange
。但是 findTest2
不在 locationRange
中。通过这种方式,indexOf()
尝试作为一个值进行搜索。但由于二维数组,它不起作用。如果使用 [13]
搜索指针,也找不到,因为 [13]
不是 locationRange
.
中的元素
模式 3
var findTest3 = [13];
var searchResult3 = locationRange.indexOf(findTest3);
在这种情况下,情况与模式2相同。
3。修改脚本
如果你想从locationRange
中搜索13
,我想你的情况,可以使用下面的修改。在这个修改后的脚本中,searchResult1
、searchResult2
和 searchResult3
是 2
.
function indexOfTest2() {
//Set sheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName("Data");
//Get ranges
var dataRange = dataSheet.getRange("A1:B7").getValues(); //data set of the locations I want to search eventually
var findRange = dataSheet.getRange("E3:E4").getValues(); //values I want to find the row of in the data set (would change in the spreadsheet based on the user's inputs)
var locationRange = dataSheet.getRange(1,1,dataSheet.getLastRow()).getValues(); //smaller range of the locations I want to locate (1st column)
// Below script was modified.
locationRange = Array.prototype.concat.apply([], locationRange);
var findTest1 = locationRange[2];
var searchResult1 = locationRange.indexOf(findTest1);
var findTest2 = findRange[0][0];
var searchResult2 = locationRange.indexOf(findTest2);
var findTest3 = [13][0];
var searchResult3 = locationRange.indexOf(findTest3);
}
注:
Array.prototype.concat.apply([], locationRange)
将 [["Location #","State"],[11,"AK"],[13,"NE"],[17,"FL"],[24,"IL"],[47,"IL"],[69,"NV"]]
的二维数组转换为 ["Location #",11,13,17,24,47,69]
的一维数组。
- 在
findTest1
处使用了locationRange[2]
,因为locationRange
是一维数组。
- 在
findTest2
处使用了var findTest2 = findRange[0][0]
,因为findRange
是二维数组。
- 在
findTest3
处,使用 var findTest3 = [13][0]
因为它从 [13]
. 检索 13
4。参考资料:
如果这不是你想要的,我很抱歉。
根据 JavaScript 规范,Array#indexOf
uses strict equality comparison:
indexOf()
compares searchElement
to elements of the Array
using strict equality (the same method used by the ===
or triple-equals operator).
严格相等,在相同类型的 Object
的术语中,意味着对象 A 必须是与对象 B 完全相同的对象引用才能使 A === B
成为 true
。具有相同值的两个对象并不意味着它们具有相同的对象引用:
var A = ['A', 'B', 'C'];
var B = ['A', 'B', 'C'];
Logger.log(A === B) // false
B = A;
Logger.log(A === B) // true
B = A.slice(0);
Logger.log(A === B) // false
Logger.log(A.map(function (ai, i) { return ai === B[i]; })); // true, true, true
在较新的 JS 版本中,您可以使用 Array#includes
来执行基于值的比较。但是,Apps Script 只是 JS 1.6(带有一些铃声和口哨声),但 includes
不是其中之一。
我试图找到一种在 Google 脚本中搜索数组的方法,但一直找不到任何可行的方法。我的最终目标是对 Google Sheet 中的多个数组进行 vlookup,对它们执行函数,然后将它们推入另一个数组以进行粘贴以供分析。我需要执行大约 2,500 个循环,因此我尽量避免 reading/writing。这是我的主要障碍的一个极其简单的版本。
当我在一个数组中查找数字的索引时,除了 -1 之外我无法得到任何其他内容,除非我正在查找该数组的一个子集。当我寻找不同数组的精确副本或对它进行硬编码时,我得不到一致的结果。预先感谢您的帮助和耐心等待!
这是我 spreadsheet 的 link,这里有一张图片供快速参考:
这是我尝试使用的代码,表明我得到了不同的索引,我认为应该是相同的结果:
function indexOfTest() {
//Set sheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName("Data");
//Get ranges
var dataRange = dataSheet.getRange("A1:B7").getValues(); //data set of the locations I want to search eventually
var findRange = dataSheet.getRange("E3:E4").getValues(); //values I want to find the row of in the data set (would change in the spreadsheet based on the user's inputs)
var locationRange = dataSheet.getRange(1,1,dataSheet.getLastRow()).getValues(); //smaller range of the locations I want to locate (1st column)
//test showing that indexOf works when I search for a subset of the array within the array
var findTest1 = locationRange[2]; //set variable to a subset of the array I will search
var searchResult1 = locationRange.indexOf(findTest1); //finding the index of the subset of the array within the array
//test showing that indexOf does NOT work when I search for the exact same value in the same array
var findTest2 = findRange[0]; //set variable to the the user-entered cell on the sheet which is exactly the same as the subset of the array from the first test
var searchResult2 = locationRange.indexOf(findTest2); //this comes back as -1 for some reason
//test showing that I can't even find it when I hard code it to exactly the same as somethng in the array that I was able to find earlier
var findTest3 = [13]; //hardcoded variable to exactly the same as the subset of the array from the first test
var searchResult3 = locationRange.indexOf(findTest3); //this comes back as -1 for some reason
var x = 1 // this is where I have the debug spot (x = 1 is meaningless but wanted the debugger to stop here)
// why does the indexOf function work for the first test but not the other two?!?!?!?
// any help would be greatly appreciated! thanks!
}
当我查看调试器时,我不明白为什么我在两个测试中得到 -1 但它在一个测试中有效...而且他们正在搜索完全相同的东西!
拜托了,非常感谢!
这个答案怎么样?
getValues()
检索到的值是二维数组。
对于您的情况,这是非常重要的一点。
1。准备
作为准备,它确认了dataRange
、findRange
、locationRange
、findTest1
、findTest2
和findTest3
的值。
检索到dataRange
、findRange
、locationRange
时,如下
dataRange = [["Location #","State"],[11,"AK"],[13,"NE"],[17,"FL"],[24,"IL"],[47,"IL"],[69,"NV"]]
findRange = [[13],["State"]]
locationRange = [["Location #"],[11],[13],[17],[24],[47],[69]]
和findTest1
、findTest2
和findTest3
是[13]
。
2。实验
在这里,它想到了使用 findTest1
、findTest2
和 findTest3
进行搜索的大约 3 种模式。
模式 1
var findTest1 = locationRange[2];
var searchResult1 = locationRange.indexOf(findTest1);
在这种情况下,from [13]
是从 [["Location #"],[11],[13],[17],[24],[47],[69]]
开始搜索的,即 locationRange
。但是 findTest1
在 locationRange
中。这行得通。我认为是因为 indexOf()
可能会使用同一数组中的元素引用来自同一数组的指针。作为另一个示例,请参阅以下示例脚本。
var ar = [[1, 2, 3], [4, 5, 6], [4, 5, 6], [7, 8, 9]];
var r1 = ar.indexOf([4, 5, 6]); // -1
var r2 = ar.indexOf(ar[2]); // 2
在这个脚本中,indexOf()
可以使用同一个二维数组中的元素。在Array.prototype.indexOf()
处,当查找的值是一个数组时,可能会引用指针。这个结果对我来说是新发现。
模式 2
var findTest2 = findRange[0];
var searchResult2 = locationRange.indexOf(findTest2);
在这种情况下,from [13]
是从 [["Location #"],[11],[13],[17],[24],[47],[69]]
开始搜索的,即 locationRange
。但是 findTest2
不在 locationRange
中。通过这种方式,indexOf()
尝试作为一个值进行搜索。但由于二维数组,它不起作用。如果使用 [13]
搜索指针,也找不到,因为 [13]
不是 locationRange
.
模式 3
var findTest3 = [13];
var searchResult3 = locationRange.indexOf(findTest3);
在这种情况下,情况与模式2相同。
3。修改脚本
如果你想从locationRange
中搜索13
,我想你的情况,可以使用下面的修改。在这个修改后的脚本中,searchResult1
、searchResult2
和 searchResult3
是 2
.
function indexOfTest2() {
//Set sheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName("Data");
//Get ranges
var dataRange = dataSheet.getRange("A1:B7").getValues(); //data set of the locations I want to search eventually
var findRange = dataSheet.getRange("E3:E4").getValues(); //values I want to find the row of in the data set (would change in the spreadsheet based on the user's inputs)
var locationRange = dataSheet.getRange(1,1,dataSheet.getLastRow()).getValues(); //smaller range of the locations I want to locate (1st column)
// Below script was modified.
locationRange = Array.prototype.concat.apply([], locationRange);
var findTest1 = locationRange[2];
var searchResult1 = locationRange.indexOf(findTest1);
var findTest2 = findRange[0][0];
var searchResult2 = locationRange.indexOf(findTest2);
var findTest3 = [13][0];
var searchResult3 = locationRange.indexOf(findTest3);
}
注:
Array.prototype.concat.apply([], locationRange)
将[["Location #","State"],[11,"AK"],[13,"NE"],[17,"FL"],[24,"IL"],[47,"IL"],[69,"NV"]]
的二维数组转换为["Location #",11,13,17,24,47,69]
的一维数组。- 在
findTest1
处使用了locationRange[2]
,因为locationRange
是一维数组。 - 在
findTest2
处使用了var findTest2 = findRange[0][0]
,因为findRange
是二维数组。 - 在
findTest3
处,使用var findTest3 = [13][0]
因为它从[13]
. 检索
13
4。参考资料:
如果这不是你想要的,我很抱歉。
根据 JavaScript 规范,Array#indexOf
uses strict equality comparison:
indexOf()
comparessearchElement
to elements of theArray
using strict equality (the same method used by the===
or triple-equals operator).
严格相等,在相同类型的 Object
的术语中,意味着对象 A 必须是与对象 B 完全相同的对象引用才能使 A === B
成为 true
。具有相同值的两个对象并不意味着它们具有相同的对象引用:
var A = ['A', 'B', 'C'];
var B = ['A', 'B', 'C'];
Logger.log(A === B) // false
B = A;
Logger.log(A === B) // true
B = A.slice(0);
Logger.log(A === B) // false
Logger.log(A.map(function (ai, i) { return ai === B[i]; })); // true, true, true
在较新的 JS 版本中,您可以使用 Array#includes
来执行基于值的比较。但是,Apps Script 只是 JS 1.6(带有一些铃声和口哨声),但 includes
不是其中之一。