arrays - 二维数组的问题 - Google Apps 脚本
问题描述
我正在尝试遍历大量单元格来测试 A 列中的值,如果返回 true,那么我想将相邻的 3 个单元格(BD 列)存储在一个数组中,并最终将该数组粘贴到单独的工作表上。当前代码找到所有正确的值,但它将它们全部写入一行,而不是像原始数据源中的多行和 3 列。
var dataset = [],
month,
i,
j,
x = 0,
targetmonth = ss.getSheetByName("BOH").getRange("B2").getValue(),
location = ss.getSheetByName(output).getRange("D3").getValue();
for ( i = 7; i < 3000; i++){
month = ss.getSheetByName(location).getRange(i,1).getValue();
if (month == targetmonth){
for (j = 2; j<5; j++){
dataset [x] = [ss.getSheetByName(location).getRange(i,j).getValues()];
x = x + 1;
}
}
}
//I've changed the range size in line below to 360x3 which is what it should be
//but this line currently only runs when set to 1x360
ss.getSheetByName(output).getRange(8,3,360,3).setValues([dataset]);
解决方案
遵循最佳实践,您应该通过使用getValues()
. 您当前的脚本循环访问 A7:A2999 的值,当它可以在一次读取中完成时:
// const x -> no reassignment / redeclaring x allowed. (You can still manipulate the object).
const startRow = 7, endRow = 2999,
numRows = endRow - startRow + 1;
const months = ss.getSheetByName(location)
.getRange(startRow, 1, numRows, 1).getValues();
然后,您有条件地访问同一范围的 B:D 列。您会发现在开始时将所有内容全部读入内存仍然更快,并且仅在需要时访问所需的行和列:
const startCol = 2, endCol = 4,
numCols = endCol - startCol + 1;
const targetValues = ss.getSheetByName(location)
.getRange(startRow, startCol, numRows, numCols).getValues();
您还应该使用比i
and更有意义的迭代索引名称j
,并且当使用点更有意义时,您不必在函数的开头声明所有内容(阅读 JavaScript 和“提升”)。
然后你的函数的其余部分如下所示:
const output = [],
targetMonth = /** set this */,
destinationName = /** set this */;
for (var monthIndex = 0; monthIndex < months.length; ++monthIndex) {
// Add the array of target column values to the output (by reference)
if (months[monthIndex][0] === targetMonth) {
output.push(targetValues[monthIndex]);
}
}
// Write the output array.
ss.getSheetByName(destinationName).getRange(8, 3, output.length, output[0].length).setValues(output);
我们刚刚从 ~numRows x numColumns 电子表格访问次数增加到 ~4!考虑到单个小区访问调用大约需要 0.1 秒,这将更快。是的,如果您读取大量单元格,可能需要一段时间(从 400k 单元格获取/设置值大约需要 30 秒),但只要 1-by-1 访问,它就不会花费太多时间。
参考:
PS:如果您在targetValues
序列化数据之前更改了值,则引用的值output
也会更新,因为它们是同一个对象。(阅读“按值”/深拷贝和“按引用”/浅拷贝以了解原因。对于编写的这个脚本,区别并不重要,因为它们没有被修改。)
推荐阅读
- tsql - SQL Server 中的日期 CAST 引发日期转换失败
- javascript - 带有 HTML 画布的 2D 光照
- python - 如何使用 Beautiful Soup 从按钮中提取文本?
- python - Python Webscraping 来自 Weather API 的表格元素
- oracle - Oracle:使用 where 子句的更新命令区分大小写?
- postgresql - 错误:PostgreSQL 11 中不存在列 p.proisagg
- azure - azure 函数代理在 Linux 系统上不起作用
- rust - 为 Rust 的超 http crate 使用自定义传输器
- javascript - Jquery - 每个获取值,查找差异并转换为数组
- python - 发送 dm 消息 discord.py 的问题