You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移除邮箱列表中的‘复杂重复项’技术解决方案问询

如何修改Google Sheets去重脚本以识别同一用户的邮箱变体重复项?

这是个很常见的邮箱去重场景——很多邮箱服务商允许用户在本地部分用.、-、_做分隔,实际却指向同一个收件箱。要解决这个问题,核心是给每个邮箱生成一个标准化的唯一标识,让所有变体都映射到同一个值,然后用这个标识来判断重复。

先看你的问题背景:

我在处理邮箱列表时遇到如下问题:同一用户存在多种格式的重复邮箱地址,例如Jane的邮箱包含jane.doe@email.com、doe.jane@email.com等变体,还包括用-或_替换.的情况。目前我使用的由@Jordan Running和Ed Nelson协助升级的去重脚本仅能处理"严格重复项",无法识别此类"复杂重复项"。请问如何修改脚本,确保同一用户仅保留一个指向同一收件箱的邮箱地址?

你当前使用的代码:

function removeDuplicates() { 
  const startTime = new Date(); 
  const newData = []; 
  const sheet = SpreadsheetApp.getActiveSheet(); 
  const data = sheet.getDataRange().getValues(); 
  const numRows = data.length; 
  const seen = {}; 
  for (var i = 0, row, key; i < numRows && (row = data[i]); i++) { 
    key = JSON.stringify(row); 
    if (key in seen) { 
      continue; 
    } 
    seen[key] = true; 
    newData.push(row); 
  }; 
  sheet.clearContents(); 
  sheet.getRange(1, 1, newData.length, newData[0].length).setValues(newData); 
  // Show summary 
  const secs = (new Date() - startTime) / 1000; 
  SpreadsheetApp.getActiveSpreadsheet().toast( 
    Utilities.formatString('Processed %d rows in %.2f seconds (%.1f rows/sec); %d deleted', numRows, secs, numRows / secs, numRows - newData.length), 
    'Remove duplicates', 
    -1); 
}

解决方案:添加邮箱标准化逻辑

1. 核心思路

我们需要新增一个邮箱标准化函数,把所有变体转换成统一格式:

  • 邮箱地址不区分大小写,先转成小写
  • 把本地部分(@符号之前的内容)的.、-、_全部移除(因为这些符号在多数邮箱服务商中不影响收件)
  • 域名部分保持不变(域名的符号不能随意修改)

2. 修改后的完整脚本

function removeDuplicates() { 
  const startTime = new Date(); 
  const newData = []; 
  const sheet = SpreadsheetApp.getActiveSheet(); 
  const data = sheet.getDataRange().getValues(); 
  const numRows = data.length; 
  const seenEmails = {};
  // 👉 这里修改邮箱所在的列索引:A列=0,B列=1,C列=2,以此类推
  const EMAIL_COLUMN_INDEX = 1;

  // 邮箱标准化函数:把所有变体转换成统一格式
  function normalizeEmail(email) {
    if (!email || typeof email !== 'string') return email;
    const emailLower = email.toLowerCase();
    const atIndex = emailLower.indexOf('@');
    if (atIndex === -1) return emailLower; // 无效邮箱(无@)直接返回小写
    const localPart = emailLower.slice(0, atIndex);
    const domain = emailLower.slice(atIndex);
    // 移除本地部分的所有.、-、_符号
    const normalizedLocal = localPart.replace(/[._-]/g, '');
    return `${normalizedLocal}${domain}`;
  }

  for (var i = 0, row, email, normalizedEmail; i < numRows && (row = data[i]); i++) { 
    email = row[EMAIL_COLUMN_INDEX];
    normalizedEmail = normalizeEmail(email);
    
    // 表头行直接保留,不参与重复判断
    if (i === 0) {
      newData.push(row);
      seenEmails[normalizedEmail] = true;
      continue;
    }

    // 如果这个标准化邮箱已经出现过,跳过当前行
    if (normalizedEmail in seenEmails) { 
      continue; 
    } 
    seenEmails[normalizedEmail] = true; 
    newData.push(row); 
  }; 

  sheet.clearContents(); 
  sheet.getRange(1, 1, newData.length, newData[0].length).setValues(newData); 

  // 显示处理总结
  const secs = (new Date() - startTime) / 1000; 
  SpreadsheetApp.getActiveSpreadsheet().toast( 
    Utilities.formatString('Processed %d rows in %.2f seconds (%.1f rows/sec); %d deleted', numRows, secs, numRows / secs, numRows - newData.length), 
    'Remove duplicates', 
    -1); 
}

3. 关键修改说明

  • 邮箱列配置:通过EMAIL_COLUMN_INDEX变量指定邮箱所在的列,根据你的表格调整即可
  • 标准化函数:normalizeEmail会把jane.doe@email.com、jane-doe@email.com、Jane_Doe@Email.COM全部转换成janedoe@email.com,这样所有变体都会被识别为同一个邮箱
  • 表头处理:特意保留了第一行(表头)的逻辑,避免表头被误判为重复项
  • 无效邮箱兼容:对于没有@的无效邮箱,脚本会转成小写后作为唯一标识,不会误删

4. 自定义调整建议

如果你需要优先保留特定格式的邮箱(比如优先保留带.的原始版本),可以调整循环逻辑:先遍历所有行,为每个标准化邮箱记录第一次出现的行(或者你偏好的行),最后再把这些行写入表格。

内容的提问来源于stack exchange,提问作者Ed Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:39:38