如何将重复的单元格与 google 应用程序脚本合并在一起?
How do I merge duplicate cells together with google app script?
我目前有一个包含两列的列表。第一列是学生姓名,第二列是他们的分数。
我从多个电子表格中导入了这份名单,所以学生的名字有很多重复的地方。我可以删除重复项,但我想统计他们的总分。例如:
艾米 10
鲍勃 9
颂歌 15
艾米 12
会变成:
艾米 22
鲍勃 9
颂歌 15
这是我目前拥有的:
var target = SpreadsheetApp.getActiveSpreadsheet();
var sheet = target.getSheetByName("Sheet2");
var data = sheet.getRange("A2:B1000").getValues();
var newData = new Array();
var k = 0
var finallist = []
for(i in data){
k++;
var row = data[i];
var duplicate = false;
for(j in newData){
if(row[0] == newData[j][0]){
duplicate = true;
var storedHour = sheet.getRange("B"+k).getValue();
var position = finallist.indexOf(row[0]);
var originalCell = sheet.getRange("B"+(position+1));
var originalHour = originalCell.getValue();
originalCell.setValue(originalHour + storedHour);
sheet.getRange(k,2).setValue("")
sheet.getRange(k,1).setValue("")
}
}
if(!duplicate){
newData.push(row);
finallist.push(row[0])
}
}
}
我遇到的问题是我们有一个非常大的数据样本,恐怕它可能 运行 超过 Google 的 5 分钟最长执行时间。还有其他更有效的方法来实现我的目标吗?
您的代码 运行 很慢,因为电子表格 API 方法(如 getRange
)比其他 JavaScript 代码耗时且慢得多。
这是减少了此类电子表格 API 调用次数的优化函数:
function calcNumbers()
{
var target = SpreadsheetApp.getActiveSpreadsheet();
var sheet = target.getSheetByName("Sheet2");
var lastRow = sheet.getLastRow();
var dataRange = sheet.getRange(2, 1, lastRow-1, 2);
var data = dataRange.getValues();
var pointsByName = {};
for (var i = 0; i < data.length; i++)
{
var row = data[i];
var curName = row[0];
var curNumber = row[1];
// empty name
if (!curName.trim())
{
continue;
}
// if name found first time, save it to object
if (!pointsByName[curName])
{
pointsByName[curName] = Number(curNumber);
}
// if duplicate, sum numbers
else
{
pointsByName[curName] += curNumber;
}
}
// prepare data for output
var outputData = Object.keys(pointsByName).map(function(name){
return [name, pointsByName[name]];
});
// clear old data
dataRange.clearContent();
// write calculated data
var newDataRange = sheet.getRange(2, 1, outputData.length, 2);
newDataRange.setValues(outputData);
}
比较前排序允许只查看下一个项目,而不是每次迭代的所有项目。一个溢出的好处是决赛名单的结果是按字母顺序排列的。执行时间显着减少。
function sumDups() {
var target = SpreadsheetApp.getActiveSpreadsheet();
var sheet = target.getSheetByName("Sheet2");
var data = sheet.getRange("A2:B" + sheet.getLastRow()).getValues().sort();
var finallist = [];
for(var i = 0; i<= data.length - 1; i++){
var hours = data[i][1];
while((i < data.length - 1) && (data[i][0] == data[i+1][0])) {
hours += data[i+1][1];
i++;
};
finallist.push([data[i][0], hours]);
};
Logger.log(finallist);
}
编辑:名称位于第一列的简单数据结构允许这样做。对于更复杂的理解和应用@Kos 的回答中显示的方法是更可取的
我目前有一个包含两列的列表。第一列是学生姓名,第二列是他们的分数。
我从多个电子表格中导入了这份名单,所以学生的名字有很多重复的地方。我可以删除重复项,但我想统计他们的总分。例如:
艾米 10 鲍勃 9 颂歌 15 艾米 12
会变成:
艾米 22 鲍勃 9 颂歌 15
这是我目前拥有的:
var target = SpreadsheetApp.getActiveSpreadsheet();
var sheet = target.getSheetByName("Sheet2");
var data = sheet.getRange("A2:B1000").getValues();
var newData = new Array();
var k = 0
var finallist = []
for(i in data){
k++;
var row = data[i];
var duplicate = false;
for(j in newData){
if(row[0] == newData[j][0]){
duplicate = true;
var storedHour = sheet.getRange("B"+k).getValue();
var position = finallist.indexOf(row[0]);
var originalCell = sheet.getRange("B"+(position+1));
var originalHour = originalCell.getValue();
originalCell.setValue(originalHour + storedHour);
sheet.getRange(k,2).setValue("")
sheet.getRange(k,1).setValue("")
}
}
if(!duplicate){
newData.push(row);
finallist.push(row[0])
}
}
}
我遇到的问题是我们有一个非常大的数据样本,恐怕它可能 运行 超过 Google 的 5 分钟最长执行时间。还有其他更有效的方法来实现我的目标吗?
您的代码 运行 很慢,因为电子表格 API 方法(如 getRange
)比其他 JavaScript 代码耗时且慢得多。
这是减少了此类电子表格 API 调用次数的优化函数:
function calcNumbers()
{
var target = SpreadsheetApp.getActiveSpreadsheet();
var sheet = target.getSheetByName("Sheet2");
var lastRow = sheet.getLastRow();
var dataRange = sheet.getRange(2, 1, lastRow-1, 2);
var data = dataRange.getValues();
var pointsByName = {};
for (var i = 0; i < data.length; i++)
{
var row = data[i];
var curName = row[0];
var curNumber = row[1];
// empty name
if (!curName.trim())
{
continue;
}
// if name found first time, save it to object
if (!pointsByName[curName])
{
pointsByName[curName] = Number(curNumber);
}
// if duplicate, sum numbers
else
{
pointsByName[curName] += curNumber;
}
}
// prepare data for output
var outputData = Object.keys(pointsByName).map(function(name){
return [name, pointsByName[name]];
});
// clear old data
dataRange.clearContent();
// write calculated data
var newDataRange = sheet.getRange(2, 1, outputData.length, 2);
newDataRange.setValues(outputData);
}
比较前排序允许只查看下一个项目,而不是每次迭代的所有项目。一个溢出的好处是决赛名单的结果是按字母顺序排列的。执行时间显着减少。
function sumDups() {
var target = SpreadsheetApp.getActiveSpreadsheet();
var sheet = target.getSheetByName("Sheet2");
var data = sheet.getRange("A2:B" + sheet.getLastRow()).getValues().sort();
var finallist = [];
for(var i = 0; i<= data.length - 1; i++){
var hours = data[i][1];
while((i < data.length - 1) && (data[i][0] == data[i+1][0])) {
hours += data[i+1][1];
i++;
};
finallist.push([data[i][0], hours]);
};
Logger.log(finallist);
}
编辑:名称位于第一列的简单数据结构允许这样做。对于更复杂的理解和应用@Kos 的回答中显示的方法是更可取的