[英]Replace Rows in Array using Google Apps Script
I'm still getting my head around Apps Script and just need some help editing an array.我仍然在关注 Apps 脚本,只是需要一些帮助来编辑数组。
So I have two arrays:所以我有两个数组:
var arrayBig = SpreadsheetApp.getSheetByName('Big').getDataRange().getValues();
var arraySmall = SpreadsheetApp.getSheetByName('Small').getDataRange().getValues();
And I want to replace specific rows in arrayBig
based on values in arraySmall
, and then write that array back to my spreadsheet (the last part I'm ok with).我想,以取代在特定行
arrayBig
基于价值观arraySmall
,然后写该数组回到我的电子表格(我确定与最后一部分)。
The two arrays have the same number of columns, but arraySmall
has fewer rows.这两个数组的列数相同,但
arraySmall
的行数较少。
The rows to replace:要替换的行:
arraySmall
replace that row in arrayBig
.arraySmall
替换该行arrayBig
。 So if the value in Column 1 = 3 replace row number 3 in arrayBig
with the contents of the row from arraySmall
where Column 1 = 3.因此,如果列 1 = 3 中的值将
arrayBig
行号 3 替换为列 1 = 3 中来自arraySmall
的行的内容。
I think the answer has to do with the map method but I don't understand it.我认为答案与map 方法有关,但我不明白。 Just some pointers to get me started would be much appreciated, thank you.
只是一些让我开始的指针将不胜感激,谢谢。
Here is one "get you started" approach:这是一种“让你开始”的方法:
You describe your data, but you do not provide any concrete samples - so here is my starting data, making some assumptions based on the information in the question:你描述了你的数据,但你没有提供任何具体的样本 - 所以这是我的起始数据,根据问题中的信息做出一些假设:
var arrayBig = [ [1, "A", "B"], [2, "C", "D"], [3, "E", "F"], [4, "G", "H"] ];
var arraySmall = [ [1, "P", "Q"], [3, "Y", "Z"] ];
With the above data, the expected outcome is the following, where rows 1 and 3 are replaced:使用上述数据,预期结果如下,其中第 1 行和第 3 行被替换:
[ [1, "P", "Q"], [2, "C", "D"], [3, "Y", "Z"], [4, "G", "H"] ];
Here is the approach:这是方法:
var arrayBig = [ [1, "A", "B"], [2, "C", "D"], [3, "E", "F"], [4, "G", "H"] ]; var arraySmall = [ [1, "P", "Q"], [3, "Y", "Z"] ]; var mapper = new Map(); arraySmall.forEach((row) => { mapper.set(row[0], row); } ); newArrayBig = []; arrayBig.forEach((row) => { if ( mapper.has( row[0] ) ) { newArrayBig.push( mapper.get( row[0] ) ); } else { newArrayBig.push( row ); } } ); console.log( newArrayBig );
This assumes you have an iron-clad guarantee that there are never more rows of data in arraySmall
than there are in arrayBig
.这里假设你有一个铁一般的保证,有数据从来没有更多的行中
arraySmall
以外还有arrayBig
。 You can (and should) add some logic to test for that, for more robust code.您可以(并且应该)添加一些逻辑来测试,以获得更健壮的代码。
Notes笔记
The Map
object (not the map()
method) is central to this approach. Map
对象(不是map()
方法)是这种方法的核心。 This object provides a lookup structure: an index value, pointing to a data value:这个对象提供了一个查找结构:一个索引值,指向一个数据值:
var mapper = new Map();
arraySmall.forEach((row) => {
mapper.set(row[0], row);
} );
In our case, the index is the number in the first cell of each arraySmall
row.在我们的例子中,索引是每个
arraySmall
行的第一个单元格中的arraySmall
。 And the value it points to is the complete data array for that row, for example:它指向的值是该行的完整数据数组,例如:
1 -> [1, "P", "Q"]
3 -> [3, "Y", "Z"]
We can now use this lookup data as we iterate through each row of our arrayBig
data:我们现在可以在遍历
arrayBig
数据的每一行时使用这个查找数据:
arrayBig.forEach((row) => { ... } );
The logic inside this forEach
iterator basically says: If the map contains an array using the same number as the current arrayBig
row, then use the arraysmall
data.这个
forEach
迭代器内部的逻辑基本上是:如果映射包含一个使用与当前arrayBig
相同数字的数组,则使用arraysmall
数据。 Otherwise, use the arrayBig
data.否则,使用
arrayBig
数据。
The newArrayBig.push()
method adds that array to our results array. newArrayBig.push()
方法将该数组添加到我们的结果数组中。
You can then write this back to your spreadsheet, as needed.然后,您可以根据需要将其写回电子表格。
Just in case.以防万一。 Another solution:
另一种解决方案:
var arrayBig = [ [1,"A","B"], [2,"C","D"], [3,"E","F"], [4,"G","H"] ]; var arraySmall = [ [1,"P","Q"], [3,"Y","Z"] ]; var obj = {}; // it will be { "1":[1,"P","Q"], "3": [3,"Y","Z"] } arraySmall.forEach( x => obj[x[0]] = x ); arrayBig = arrayBig.map( x => obj[x[0]] || x ); console.log(arrayBig); // [[1,"P","Q"], [2,"C","D"], [3,"Y","Z"], [4,"G","H"]];
It converts the small array into an object where first element of every row is a key and the row is its value.它将小数组转换为一个对象,其中每一行的第一个元素是一个键,该行是它的值。 Then it loops through the big array and tries to get values of the object by keys (a first cell).
然后它遍历大数组并尝试通过键(第一个单元格)获取对象的值。 If the key exists the row will replace, if key doesn't exist the for wont change.
如果键存在,该行将被替换,如果键不存在,则 for 不会改变。
Sequence of the rows in the small array doesn't matter as well.小数组中行的顺序也无关紧要。
Updage更新
You can use an array instead of an object if you want:如果需要,您可以使用数组而不是对象:
var arrayBig = [ [1,"A","B"], [2,"C","D"], [3,"E","F"], [4,"G","H"] ]; var arraySmall = [ [1,"P","Q"], [3,"Y","Z"] ]; var arr = []; arraySmall.forEach( x => arr[x[0]-1] = x ); // [ [1,"P","Q"], [], [3,"Y","Z"], [] ]; arrayBig = arrayBig.map( (x,i) => arr[i] || x); console.log(arrayBig);
I think it will take more memory, but it works.我认为这将需要更多的内存,但它的工作原理。 But you need to be sure that first cells contain numbers only, since they're using as indexes of the array (indexes of array should be numbers, unlike keys that can be anything).
但是您需要确保第一个单元格仅包含数字,因为它们用作数组的索引(数组的索引应该是数字,不像键可以是任何东西)。 And rows of first array should be sorted and has no skipped numbers (1, 2, 3, 4, etc).
并且第一个数组的行应该被排序并且没有跳过的数字(1、2、3、4 等)。 So, it's a more fragile solution.
所以,这是一个更脆弱的解决方案。 Just for educational purposes.
仅用于教育目的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.