Google AppScript实现表格姓名去重并合并关联唯一数据
问题描述
处理包含大量重复姓名的表格:移除重复姓名行,将对应唯一数据追加至首个姓名行末尾。示例如下:
现有数组:[John Smith, General], [John Smith, Tall], [John Smith, Rich], [John Smith, Blue], [John Smith, Children], [John Smith, Tall], [John Smith, Rich]
转换后结果:[John Smith, (General, Tall, Rich, Blue, Children)]
现有代码(存在逻辑问题)
var filteredData = [] for (var i = 0; i < peopleData.length; i++){ //If name doesn't exist on filtered list, add it if (filteredData.indexOf(peopleData[i][0]) == -1){ filteredData.push([peopleData[i][0], peopleData[i][1]]); } else{ //Name already exists, add attributes to existing entry filteredData[i-1] = filteredData[i-1] + ", " + peopleData[i][1]; } }
问题分析与修正方案
你的代码存在两个核心问题:
filteredData.indexOf(peopleData[i][0])无法正确检测姓名是否存在——filteredData存储的是数组(如[John Smith, General]),直接用字符串姓名调用indexOf必然返回-1。- 追加数据时的
filteredData[i-1] = filteredData[i-1] + ", " + peopleData[i][1]会将数组强制转为字符串,破坏数据结构,且无法过滤重复属性。
推荐使用对象映射表+Set去重的方案,高效实现需求:
function processDuplicateNames(peopleData) { // 用对象存储姓名对应的属性集合(Set自动去重) const nameMap = {}; for (const [name, attr] of peopleData) { if (!nameMap[name]) { // 首次遇到姓名,初始化Set nameMap[name] = new Set(); } // 添加属性到Set,自动过滤重复值 nameMap[name].add(attr); } // 将对象转换为目标格式的数组 const filteredData = []; for (const name in nameMap) { // 把Set转为逗号分隔的字符串,再包裹括号 const attrStr = `(${Array.from(nameMap[name]).join(', ')})`; filteredData.push([name, attrStr]); } return filteredData; } // 测试示例 const peopleData = [ ["John Smith", "General"], ["John Smith", "Tall"], ["John Smith", "Rich"], ["John Smith", "Blue"], ["John Smith", "Children"], ["John Smith", "Tall"], ["John Smith", "Rich"] ]; console.log(processDuplicateNames(peopleData)); // 输出:[ [ 'John Smith', '(General, Tall, Rich, Blue, Children)' ] ]
核心要点
- Set去重:利用
Set的特性自动过滤重复属性,无需手动编写判断逻辑。 - 对象映射:以姓名为键快速定位属性集合,比遍历数组查找效率更高,尤其适合处理大量数据。
- 格式适配:将
Set转换为数组后拼接成带括号的字符串,完全符合需求格式。
如果是在Google Apps Script中处理表格,只需将peopleData替换为表格读取的数组(如SpreadsheetApp.getActiveSheet().getDataRange().getValues()),再将处理后的filteredData写回表格即可。
内容的提问来源于stack exchange,提问作者Sky Martin
相关产品推荐
相关产品推荐

